这点东西前前后后拖了好几个星期才学会……还是自己太菜啊。

Cdq分治的思想是:把问题序列分割成左右两个,先单独处理左边,再处理左边对右边的影响,再单独处理右边。这样可以消去数据结构上的一个log,降低编码复杂度。

整体二分:当一个询问的答案满足二分性质时,我们可以按照答案的大小分割整个查询和修改序列。每次把序列分成互不相同的两部分。这样能把数据结构的二分拿出来,降低编码复杂度。

说白了,就是当你懒得写树套树或者惨遭卡内存时候的骗分办法。

好了,上例题吧:

BZOJ2683:

二维单点加,矩形查。可以kdtree或树套树水过。

然而这里要用cdq分治。我们把一个查询利用二维前缀和原理拆成4个,然后按x排序,对t(时间)cdq分治,用树状数组维护y上的前缀和。我们先处理t在左边对右边查询的影响,然后再递归处理左右。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define debug cout
 6 using namespace std;
 7 const int maxn=8e5+1e2;
 8 
 9 int n;
10 
11 struct BinaryIndexTree {
12     int dat[maxn];
13     #define lowbit(x) (x&-x)
14     inline void update(int pos,int x) {
15         while( pos < maxn ) {
16             dat[pos] += x ,
17             pos += lowbit(pos);
18         }
19     }
20     inline int query(int pos) {
21         int ret = 0;
22         while( pos )
23             ret += dat[pos] ,
24             pos -= lowbit(pos);
25         return ret;
26     }
27 }bit;
28 
29 struct QNode {
30     int tpe,x,y,aid,tme,lam;
31     friend bool operator < (const QNode &a,const QNode &b) {
32         if( a.x != b.x )
33             return a.x < b.x;
34         if( a.y != b.y )
35             return a.y < b.y;
36         return a.tpe < b.tpe;
37     }
38 }ns[maxn],tp[maxn];
39 
40 int cnt,acn;
41 int ans[maxn];
42 
43 inline void cdq(int l,int r) {
44     if( l == r )
45         return;
46     const int mid = ( l + r ) >> 1;
47     for(int i=l;i<=r;i++) {
48         if( ns[i].tme <= mid && ns[i].tpe == 1 )
49             bit.update(ns[i].y,ns[i].lam);
50         if( ns[i].tme > mid && ns[i].tpe == 2 )
51             ans[ns[i].aid] += ns[i].lam * bit.query(ns[i].y);
52     }
53     for(int i=l;i<=r;i++)
54         if( ns[i].tme <= mid && ns[i].tpe == 1 )
55             bit.update(ns[i].y,-ns[i].lam);
56     int l1 = l , l2 = mid + 1;
57     for(int i=l;i<=r;i++)
58         if( ns[i].tme <= mid )
59             tp[l1++] = ns[i];
60         else
61             tp[l2++] = ns[i];
62     for(int i=l;i<=r;i++)
63         ns[i] = tp[i];
64     cdq(l,mid);
65     cdq(mid+1,r);
66 }
67 
68 int main() {
69     static int t,x,y,xx,yy,lam;
70     scanf("%d",&n);
71     while( scanf("%d",&t) == 1 && t != 3 ) {
72         if( t == 1 ) {
73             scanf("%d%d%d",&x,&y,&lam);
74             ns[++cnt].tpe = t , ns[cnt].x = x , ns[cnt].y = y ,
75             ns[cnt].lam = lam , ns[cnt].tme = cnt;
76         }
77         else {
78             scanf("%d%d%d%d",&x,&y,&xx,&yy);
79             --x , --y , ++acn;
80             ns[++cnt].tpe = t , ns[cnt].x = x , ns[cnt].y = y ,
81             ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = 1;
82             ns[++cnt].tpe = t , ns[cnt].x = xx , ns[cnt].y = yy ,
83             ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = 1;
84             ns[++cnt].tpe = t , ns[cnt].x = x , ns[cnt].y = yy ,
85             ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = -1;
86             ns[++cnt].tpe = t , ns[cnt].x = xx , ns[cnt].y = y ,
87             ns[cnt].aid = acn , ns[cnt].tme = cnt , ns[cnt].lam = -1;
88         }
89     }
90     sort(ns+1,ns+1+cnt);
91     cdq(1,cnt);
92     
93     for(int i=1;i<=acn;i++)
94         printf("%d\n",ans[i]);
95     
96     return 0;
97 }
View Code

相关文章:

  • 2022-12-23
  • 2021-07-16
  • 2021-04-05
  • 2021-09-24
  • 2021-08-28
  • 2022-12-23
猜你喜欢
  • 2021-10-07
  • 2021-12-17
  • 2021-09-09
  • 2022-12-23
  • 2022-12-23
  • 2022-01-24
  • 2021-07-02
相关资源
相似解决方案