cdq分治
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了cdq分治相关的知识,希望对你有一定的参考价值。
啊最近头好晕还要学这么多东西更晕了
心理状态也没什么转好的迹象阿 似乎是越来越喜欢放大负能量了
而且完全不想做总结 也完全写不动题qwq
大概是要废了= =
啊那么cdq分治呢大概就是利用了离线的力量
写过归并的某些题的应该能明白 大概就是你分治回来之后,中间有一部分是要再次处理的
于是cdq分治就这么将查询与修改的关系提前确定了
昨天下午才开始学我觉得大概就这样了吧 以后要有什么更深刻的理解了再回来补充qwq
现在真的整个人都发虚
1.三维偏序裸题 陌上花开
一维sort二维归并三维树状数组
入门题 基本是靠着打这份代码才明白了思想
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<string> 7 #define ll long long 8 #define db double 9 #define N 120000 10 #define inf 11 using namespace std; 12 struct hh{ 13 int s,c,m; 14 }a[N]; 15 int q[N],tree[N*4],s[N],ss[N],p[N],num[N],la[N],ans[N]; 16 int n,k,cnt=0; 17 bool cmp(hh x,hh y){ 18 if (x.s==y.s&&x.c==y.c) return x.m<y.m; 19 if (x.s==y.s) return x.c<y.c; 20 return x.s<y.s; 21 } 22 int lowbit(int x){ 23 return x&(-x); 24 } 25 void add(int x,int v){ 26 while (x<=k){ 27 tree[x]+=v; 28 x+=lowbit(x); 29 } 30 } 31 int query(int x){ 32 int ans=0; 33 while (x>0){ 34 ans+=tree[x]; 35 x-=lowbit(x); 36 } 37 return ans; 38 } 39 void merge(int l,int r){ 40 if (l==r){ 41 s[l]=l;return ; 42 } 43 int mid=(l+r)>>1; 44 merge(l,mid);merge(mid+1,r); 45 int i=l,j=mid+1; 46 for (int k=l;k<=r;++k){ 47 if (j<=r&&(i>mid||p[s[i]]>p[s[j]])) ans[s[j]]+=query(q[s[j]]),ss[k]=s[j++]; 48 else add(q[s[i]],num[s[i]]),ss[k]=s[i++]; 49 } 50 for (int k=l;k<=mid;++k) add(q[k],-num[k]); 51 for (int k=l;k<=r;++k) s[k]=ss[k]; 52 } 53 int main(){ 54 freopen ("1.in","r",stdin); 55 freopen ("1.out","w",stdout); 56 scanf ("%d%d",&n,&k); 57 for (int i=1;i<=n;++i) scanf ("%d%d%d",&a[i].s,&a[i].c,&a[i].m); 58 sort(a+1,a+n+1,cmp); 59 for (int i=1;i<=n;++i){ 60 if (a[i].s!=a[i-1].s||a[i].c!=a[i-1].c||a[i].m!=a[i-1].m) p[++cnt]=a[i].c,q[cnt]=a[i].m; 61 num[cnt]++; 62 } 63 merge(1,cnt); 64 for (int i=1;i<=cnt;++i) la[ans[i]+num[i]-1]+=num[i]; 65 for (int i=0;i<n;++i) printf ("%d\n",la[i]); 66 return 0; 67 }
2.mokia
好想写成中文
(可能是膜可鸭)
主要是询问要拆分一下 写过平面前缀和的大概能理解 另外千万不要像我一样搞个什么pq这种长得很像的放一起 用错了好久qaq
另外 排序的时候不能只管你要排序的那一个量 其他的也要判断(惨痛脸)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<string> 7 #define ll long long 8 #define db double 9 #define N 2000020 10 #define inf 11 using namespace std; 12 int a,n,cnt=0,c=0; 13 int ans[N],tree[N<<1]; 14 bool b[N]; 15 struct hh{ 16 int x,y,v,id,t,l; 17 }m[N],t[N]; 18 bool cmp(hh a,hh b){ 19 if (a.x==b.x&&a.y==b.y) return a.l<b.l; 20 if (a.x==b.x) return a.y<b.y; 21 return a.x<b.x; 22 } 23 int lowbit(int x){ 24 return x&(-x); 25 } 26 void add(int x,int v){ 27 while (x<=n){ 28 tree[x]+=v; 29 x+=lowbit(x); 30 } 31 } 32 int query(int x){ 33 int tmp=0; 34 while (x>0){ 35 tmp+=tree[x]; 36 x-=lowbit(x); 37 } 38 return tmp; 39 } 40 void merge(int l,int r){ 41 if (l==r) return ; 42 int mid=(l+r)>>1; 43 merge(l,mid);merge(mid+1,r); 44 for (int i=l;i<=r;++i) t[i]=m[i],t[i].l=(i<=mid?0:1); 45 sort(t+l,t+r+1,cmp); 46 for (int k=l;k<=r;++k){ 47 if ((!t[k].l)&&t[k].v) add(t[k].y,t[k].v); 48 else if (t[k].l&&(!t[k].v)) ans[t[k].id]+=(t[k].t*query(t[k].y)); 49 } 50 for (int k=l;k<=r;++k) 51 if ((!t[k].l)&&t[k].v) add(t[k].y,-t[k].v); 52 } 53 int main(){ 54 freopen ("mokia.in","r",stdin); 55 freopen ("mokia.out","w",stdout); 56 scanf ("%d%d",&a,&n); 57 while (1){ 58 scanf ("%d",&a); 59 if (a==3) break; 60 c++; 61 int o,p,q,r; 62 if (a==1){ 63 scanf ("%d%d%d",&o,&p,&q); 64 m[++cnt]=hh{o,p,q,c}; 65 } 66 if (a==2){ 67 b[c]=1; 68 scanf ("%d%d%d%d",&o,&p,&q,&r); 69 m[++cnt]=hh{q,r,0,c,1}; 70 m[++cnt]=hh{q,p-1,0,c,-1}; 71 m[++cnt]=hh{o-1,r,0,c,-1}; 72 m[++cnt]=hh{o-1,p-1,0,c,1}; 73 } 74 } 75 merge(1,cnt); 76 for (int i=1;i<=c;++i) if (b[i]) printf ("%d\n",ans[i]); 77 return 0; 78 }
3.动态逆序对
想着第三题也应该算入门了多自己想想吧 结果naive
原本只想到了二维(可能头晕傻了 后来渐渐感觉不对了就去看题解了
突然一下醒过来发现我是个sb 然后继续头晕
http://blog.csdn.net/u011542204/article/details/50571409 这篇博客讲得超级nice
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<algorithm> 6 #include<string> 7 #define ll long long 8 #define db double 9 #define N 101000 10 #define inf 11 using namespace std; 12 int n,m,cnt=0; 13 int tr[N<<1],p[N]; 14 ll ans[N],asn[N],la[N]; 15 struct hh{ 16 int x,y,t; 17 }s[N],t[N]; 18 int lowbit(int x){ 19 return x&(-x); 20 } 21 void add(int x,int v){ 22 while (x<=n){ 23 tr[x]+=v; 24 x+=lowbit(x); 25 } 26 } 27 int query(int x){ 28 int ans=0; 29 while (x>0){ 30 ans+=tr[x]; 31 x-=lowbit(x); 32 } 33 return ans; 34 } 35 void work(int l,int r){ 36 if (l>=r) return ; 37 int mid=(l+r)>>1; 38 int h1=l-1,h2=mid; 39 for (int i=l;i<=r;++i){ 40 if (s[i].t<=mid) t[++h1]=s[i]; 41 else t[++h2]=s[i]; 42 } 43 h1=l; 44 for (int i=mid+1;i<=r;++i){ 45 for (;h1<=mid&&t[h1].x<t[i].x;h1++) add(t[h1].y,1); 46 ans[t[i].t]+=(h1-l)-query(t[i].y); 47 } 48 for (int i=l;i<=h1-1;++i) add(t[i].y,-1); 49 h1=mid; 50 for (int i=r;i>=mid+1;--i){ 51 for (;h1>=l&&t[h1].x>t[i].x;h1--) add(t[h1].y,1); 52 asn[t[i].t]+=query(t[i].y-1); 53 } 54 for (int i=mid;i>h1;--i) add(t[i].y,-1); 55 for (int i=l;i<=r;++i) s[i]=t[i]; 56 work(l,mid);work(mid+1,r); 57 } 58 int main(){ 59 freopen ("7.in","r",stdin); 60 freopen ("7.out","w",stdout); 61 scanf ("%d%d",&n,&m); 62 int x; 63 for (int i=1;i<=n;++i){ 64 scanf ("%d",&s[i].y); 65 s[i].x=i;p[s[i].y]=i; 66 } 67 for (int i=1;i<=m;++i){ 68 scanf ("%d",&x); 69 s[p[x]].t=n-i+1; 70 } 71 int c=0; 72 for (int i=1;i<=n;++i) if (!s[i].t) s[i].t=++c; 73 work(1,n); 74 for (int i=1;i<=n;++i) la[i]=la[i-1]+ans[i]+asn[i]; 75 for (int i=n;i>=n-m+1;--i) printf("%lld\n",la[i]); 76 return 0; 77 }
然后今天好像就要过去了呀qwq
在太阳落山之前好歹再去学点什么吧= - =
以上是关于cdq分治的主要内容,如果未能解决你的问题,请参考以下文章