853C - Boredom

题意

给出一个矩阵,每行每列有且仅有一个点。每次询问一个子矩形,问这些点构成的矩形有多少个与给定的矩形相交(两个处于对角线上的点可以组成矩形)。

分析

考虑矩形周围 8 个方向,答案其实就是这些方向上的点的组合。直接去算相交比较麻烦,我们可以考虑去算不相交的矩形的个数,例如上方有 \(x\) 个点,则要减去矩形的个数 \(\frac{x * (x - 1)}{2}\) ,下左右同理,但是这样会多减去左下角、左上角、右上角、右下角四个区域的点组成的矩形的个数,考虑再加回来,那我们实际上就要高效算出这些区域内点的个数。二维平面统计点的个数,上主席树。

再讲讲主席树查询的那部分,和线段树很类似(废话)。为什么它可以统计纵轴方向上某个区间点的个数呢?注意到在插入数据的时候我们是根据值的大小去决定走左边还是右边的,在查询的时候,同样根据值的大小决定走左还是走右(这个值此时是区间端点的值)。

code

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. #define lson l, m
  5. #define rson m + 1, r
  6. const int MAXN = 2e5 + 10;
  7. int L[MAXN << 5], R[MAXN << 5], sum[MAXN << 5];
  8. int tot;
  9. int f[MAXN];
  10. int build(int l, int r) {
  11. int rt = ++tot;
  12. sum[rt] = 0;
  13. if(l < r) {
  14. int m = l + r >> 1;
  15. L[rt] = build(lson);
  16. R[rt] = build(rson);
  17. }
  18. return rt;
  19. }
  20. int update(int pre, int l, int r, int x) {
  21. int rt = ++tot;
  22. L[rt] = L[pre]; R[rt] = R[pre]; sum[rt] = sum[pre] + 1;
  23. if(l < r) {
  24. int m = l + r >> 1;
  25. if(x <= m) L[rt] = update(L[pre], lson, x);
  26. else R[rt] = update(R[pre], rson, x);
  27. }
  28. return rt;
  29. }
  30. ll query(int ql, int qr, int l_, int r_, int l, int r) {
  31. if(l >= l_ && r <= r_) return sum[qr] - sum[ql];
  32. int m = (l + r) / 2;
  33. ll res = 0;
  34. if(m >= l_) res += query(L[ql], L[qr], l_, r_, lson);
  35. if(m < r_) res += query(R[ql], R[qr], l_, r_, rson);
  36. return res;
  37. }
  38. ll cal(ll x) { return x * (x - 1) / 2; }
  39. int main() {
  40. tot = 0;
  41. int n, q;
  42. scanf("%d%d", &n, &q);
  43. f[0] = build(1, n);
  44. for(int i = 1; i <= n; i++) {
  45. int x;
  46. scanf("%d", &x);
  47. f[i] = update(f[i - 1], 1, n, x);
  48. }
  49. while(q--) {
  50. int l, d, r, u;
  51. scanf("%d%d%d%d", &l, &d, &r, &u);
  52. ll res = cal(n) - cal(l - 1) - cal(n - r) - cal(d - 1) - cal(n - u);
  53. if(d > 1) {
  54. res += cal(query(f[0], f[l - 1], 1, d - 1, 1, n));
  55. res += cal(query(f[r], f[n], 1, d - 1, 1, n));
  56. }
  57. if(u < n) {
  58. res += cal(query(f[0], f[l - 1], u + 1, n, 1, n));
  59. res += cal(query(f[r], f[n], u + 1, n, 1, n));
  60. }
  61. printf("%I64d\n", res);
  62. }
  63. return 0;
  64. }

Codeforces 853C - Boredom的更多相关文章

  1. [Codeforces Round #433][Codeforces 853C/854E. Boredom]

    题目链接:853C - Boredom/854E - Boredom 题目大意:在\(n\times n\)的方格中,每一行,每一列都恰有一个被标记的方格,称一个矩形为漂亮的当且仅当这个矩形有两个角是 ...

  2. CodeForces 456-C Boredom

    题目链接:CodeForces -456C Description Alex doesn't like boredom. That's why whenever he gets bored, he c ...

  3. CodeForces 455A Boredom (DP)

    Boredom 题目链接: http://acm.hust.edu.cn/vjudge/contest/121334#problem/G Description Alex doesn't like b ...

  4. Codeforces 455A - Boredom - [DP]

    题目链接:https://codeforces.com/problemset/problem/455/A 题意: 给出一个 $n$ 个数字的整数序列 $a[1 \sim n]$,每次你可以选择一个 $ ...

  5. Codeforces 445A Boredom(DP+单调队列优化)

    题目链接:http://codeforces.com/problemset/problem/455/A 题目大意:有n个数,每次可以选择删除一个值为x的数,然后值为x-1,x+1的数也都会被删除,你可 ...

  6. Codeforces 455A Boredom (线性DP)

    <题目链接> 题目大意:给定一个序列,让你在其中挑选一些数,如果你选了x,那么你能够得到x分,但是该序列中所有等于x-1和x+1的元素将全部消失,问你最多能够得多少分. 解题分析:从小到大 ...

  7. Codeforces 455A Boredom 取数字的dp

    题目链接:点击打开链接 给定一个n长的序列 删除x这个数就能获得x * x的个数 的分数,然后x+1和x-1这2个数会消失.即无法获得这2个数的分数 问最高得分. 先统计每一个数出现的次数.然后dp一 ...

  8. Codeforces Round #260 (Div. 1) A - Boredom DP

    A. Boredom Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/455/problem/A ...

  9. DP Codeforces Round #260 (Div. 1) A. Boredom

    题目传送门 /* 题意:选择a[k]然后a[k]-1和a[k]+1的全部删除,得到点数a[k],问最大点数 DP:状态转移方程:dp[i] = max (dp[i-1], dp[i-2] + (ll) ...

随机推荐

  1. DataBase -- Employees Earning More Than Their Managers My Submissions Question

    Question: The Employee table holds all employees including their managers. Every employee has an Id, ...

  2. [洛谷P2602][ZJOI2010]数字计数

    题目大意:求区间$[l,r]$中数字$0\sim9$出现个数 题解:数位$DP$ 卡点:无 C++ Code: #include <cstdio> #include <iostrea ...

  3. POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

    题目: POJ最近总是炸 所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157 题解: 题很长,但其实就是给个有源汇带下界网络流(+是源,-是 ...

  4. AOJ.602 大家来找茬

    大家来找茬 Time Limit: 1000 ms Case Time Limit: 1000 ms Memory Limit: 64 MB Total Submission: 627 Submiss ...

  5. 【BZOJ1458】士兵占领 最大流的模板题

    我们只要把他们可以有的限制用流量限制,再用两者关系限制一下就可以开心的跑了. #include <cstdio> #include <cstring> #include < ...

  6. 开发中常遇到的Python陷阱和注意点

    最近使用Python的过程中遇到了一些坑,例如用datetime.datetime.now()这个可变对象作为函数的默认参数,模块循环依赖等等. 在此记录一下,方便以后查询和补充. 避免可变对象作为默 ...

  7. 理解PHP链式调用

    php链式操作:类似如下实现 $db->where()->limit()->order(); 不使用链式调用时的代码格式如下: namespace Database; class D ...

  8. Spring学习--通过注解配置 Bean (二)

    在 classpath 中扫描组件: 当在组件类上使用了特定的注解之后 , 还需要在 Spring 的配置文件中声明 <context:component-scan>: base-pack ...

  9. Swift开发学习(二):Playground

    http://blog.csdn.net/powerlly/article/details/29674253 Swift开发学习:Playground 关于 对于软件用户.游戏玩家,大家一直都在提倡用 ...

  10. kvm源代码分析

    vmx是x86硬件虚拟化层,从代码看,qemu用户态是一层,kernel中KVM通用代码是一层,类似kvm_x86_ops是一层,针对各个不同的硬件架构,而vcpu_vmx则是具体架构的虚拟化方案一层 ...