[关闭]
@l1ll5 2020-05-04T14:16:45.000000Z 字数 4135 阅读 1004

CDQ分治

流程:

需要注意的通常需要反复按照不同规则排序以消除影响。

引入:

三(二)维LIS问题

时间轴、x轴、y轴

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #define N 100010
  5. using namespace std;
  6. struct data
  7. {
  8. int p , x , y , dp;
  9. }a[N];
  10. int n , f[N] , v[N];
  11. bool cmp1(data a , data b)
  12. {
  13. return a.x < b.x;
  14. }
  15. bool cmp2(data a , data b)
  16. {
  17. return a.p < b.p;
  18. }
  19. void add(int x , int a)
  20. {
  21. int i;
  22. for(i = x ; i <= n ; i += i & -i) f[i] = max(f[i] , a);
  23. }
  24. int query(int x)
  25. {
  26. int i , ans = 0;
  27. for(i = x ; i ; i -= i & -i) ans = max(ans , f[i]);
  28. return ans;
  29. }
  30. void clear(int x)
  31. {
  32. int i;
  33. for(i = x ; i <= n ; i += i & -i) f[i] = 0;
  34. }
  35. void solve(int l , int r)
  36. {
  37. if(l >= r) return;
  38. int mid = (l + r) >> 1 , p1 = l , p2 = mid + 1 , i;
  39. solve(l , mid) , sort(a + l , a + mid + 1 , cmp1) , sort(a + mid + 1 , a + r + 1 , cmp1);
  40. while(p2 <= r)
  41. {
  42. if(p1 <= mid && a[p1].x < a[p2].x) add(a[p1].y , a[p1].dp) , p1 ++ ;
  43. else a[p2].dp = max(a[p2].dp , query(a[p2].y - 1) + 1) , p2 ++ ;
  44. }
  45. for(i = l ; i <= mid ; i ++ ) clear(a[i].y);
  46. sort(a + mid + 1 , a + r + 1 , cmp2) , solve(mid + 1 , r);
  47. }
  48. int main()
  49. {
  50. int i , ans = 0;
  51. scanf("%d" , &n);
  52. for(i = 1 ; i <= n ; i ++ ) scanf("%d%d" , &a[i].x , &a[i].y) , a[i].p = i , v[i] = a[i].y , a[i].dp = 1;
  53. sort(v + 1 , v + n + 1);
  54. for(i = 1 ; i <= n ; i ++ ) a[i].y = lower_bound(v + 1 , v + n + 1 , a[i].y) - v;
  55. solve(1 , n);
  56. for(i = 1 ; i <= n ; i ++ ) ans = max(ans , a[i].dp);
  57. printf("%d\n" , ans);
  58. return 0;
  59. }

三维偏序问题

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using namespace std;
  5. struct flower{
  6. int x,y,z;
  7. int cnt,ans;
  8. }d[1000010];
  9. int tree[3000010],n,k,tot,num[1000010];
  10. int tmp(flower a,flower b)
  11. {
  12. if(a.x<b.x) return 1;
  13. if(a.x>b.x) return 0;
  14. if(a.y<b.y) return 1;
  15. if(a.y>b.y) return 0;
  16. if(a.z<b.z) return 1;
  17. return 0;
  18. }
  19. int cmp(flower a,flower b)
  20. {
  21. if(a.y<b.y) return 1;
  22. if(a.y>b.y) return 0;
  23. if(a.z<b.z) return 1;
  24. if(a.z>b.z) return 0;
  25. if(a.x<b.x) return 1;
  26. return 0;
  27. }
  28. inline int lowbit(int x)
  29. {
  30. return x&(-x);
  31. }
  32. inline void updata(int x,int v)
  33. {
  34. while(x<=k)
  35. {
  36. tree[x]+=v;
  37. x+=lowbit(x);
  38. }
  39. return;
  40. }
  41. inline int ask(int x)
  42. {
  43. int sum=0;
  44. while(x)
  45. {
  46. sum+=tree[x];
  47. x-=lowbit(x);
  48. }
  49. return sum;
  50. }
  51. void CDQ(int l,int r)
  52. {
  53. if(l==r)
  54. {
  55. d[l].ans+=d[l].cnt-1;
  56. return;
  57. }
  58. int mid=(l+r)>>1;
  59. CDQ(l,mid);
  60. sort(d+l,d+mid+1,cmp);
  61. sort(d+mid+1,d+r+1,cmp);
  62. int j=l;
  63. for(int i=mid+1;i<=r;++i)
  64. {
  65. while(j<=mid&&d[j].y<=d[i].y)
  66. updata(d[j].z,d[j].cnt),++j;
  67. d[i].ans+=ask(d[i].z);
  68. }
  69. for(int i=l;i<j;++i) updata(d[i].z,-d[i].cnt);
  70. sort(d+mid+1,d+r+1,tmp);
  71. CDQ(mid+1,r);
  72. }
  73. int main()
  74. {
  75. int i,j;
  76. scanf("%d%d",&n,&k);
  77. for(i=1;i<=n;++i) scanf("%d%d%d",&d[i].x,&d[i].y,&d[i].z),d[i].ans=1;
  78. sort(d+1,d+n+1,tmp);
  79. for(i=1;i<=n;++i)
  80. if(i!=1&&d[i].x==d[i-1].x&&d[i].y==d[i-1].y&&d[i].z==d[i-1].z) d[tot].cnt++;
  81. else d[++tot]=d[i],d[tot].cnt=1;
  82. CDQ(1,tot);
  83. sort(d+1,d+tot+1,tmp);
  84. for(i=1;i<=tot;++i) num[d[i].ans]+=d[i].cnt;
  85. for(i=1;i<=n;++i) printf("%d\n",num[i]);
  86. return 0;
  87. }

离线问题相关:

伪强制在线: Codeforces 1217F —— 线段树分治

记录所有可能的操作,解码决定是否执行。

数据结构问题:时间轴,操作空间。

时间轴:自动有序
在线:k维数据结构维护k维空间
离线:处理左区间对右区间的影响,分治结构保证了“相对有序”。可以对另一维进行排序。用k-1维数据结构维k维空间即可。
上述过程可以反复嵌套直至便于实现。

整体二分:
[POI2011]MET-Meteors

  1. #include <cmath>
  2. #include <queue>
  3. #include <cstdio>
  4. #include <vector>
  5. #include <iomanip>
  6. #include <cstdlib>
  7. #include <cstring>
  8. #include <iostream>
  9. #include <algorithm>
  10. #define N 300010
  11. #define ll long long
  12. #define inf 1000000000
  13. using namespace std;
  14. char xB[1<<15],*xS=xB,*xT=xB;
  15. #define getchar() (xS==xT&&(xT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xT)?0:*xS++)
  16. inline int read()
  17. {
  18. int x=0,f=1;char ch=getchar();
  19. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  20. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  21. return x*f;
  22. }
  23. int n,m,k,p[N],l[N],r[N],v[N],ans[N],T;
  24. int d[N],tmp[N];
  25. bool ck[N];
  26. vector<int> a[N];
  27. ll c[N];
  28. int add(int x,int v)
  29. {
  30. for(;x<=m;x+=x&(-x))
  31. c[x]+=v;
  32. }
  33. ll ask(int x)
  34. {
  35. ll ret=0;
  36. for(;x;x-=x&(-x))
  37. ret+=c[x];
  38. return ret;
  39. }
  40. void cal(int x,int f)
  41. {
  42. if(l[x]<=r[x])
  43. add(l[x],v[x]*f),add(r[x]+1,-v[x]*f);
  44. else add(1,v[x]*f),add(r[x]+1,-v[x]*f),add(l[x],v[x]*f);
  45. }
  46. void solve(int l,int r,int L,int R)//处理 l~r国家 答案区间L~R
  47. {
  48. if(l>r)return ;
  49. if(L==R)
  50. {
  51. for(int i=l;i<=r;i++)
  52. ans[d[i]]=L;
  53. return ;
  54. }
  55. int mid=(L+R)>>1;
  56. while(T<=mid)T++,cal(T,1);
  57. while(T>mid)cal(T,-1),T--;
  58. int cnt=0;
  59. for(int i=l;i<=r;i++)
  60. {
  61. ll ret=0;
  62. for(int j=0;j<a[d[i]].size();j++)
  63. {
  64. ret+=ask(a[d[i]][j]);
  65. if(ret>=p[d[i]])break ;
  66. }
  67. if(ret>=p[d[i]])ck[d[i]]=1,cnt++;
  68. else ck[d[i]]=0;
  69. }
  70. int l_=l,r_=l+cnt;
  71. for(int i=l;i<=r;i++)
  72. {
  73. if(ck[d[i]])tmp[l_++]=d[i];
  74. else tmp[r_++]=d[i];
  75. }
  76. for(int i=l;i<=r;i++)d[i]=tmp[i];
  77. solve(l,l_-1,L,mid);solve(l_,r_-1,mid+1,R);
  78. }
  79. int main()
  80. {
  81. n=read(),m=read();
  82. for(int i=1;i<=m;i++)
  83. {
  84. int x=read();
  85. a[x].push_back(i);
  86. }
  87. for(int i=1;i<=n;i++)
  88. p[i]=read(),d[i]=i;
  89. k=read();
  90. for(int i=1;i<=k;i++)
  91. l[i]=read(),r[i]=read(),v[i]=read();
  92. l[++k]=1,r[k]=m,v[k]=inf;
  93. solve(1,n,1,k);
  94. for(int i=1;i<=n;i++)
  95. printf(ans[i]==k?"NIE\n":"%d\n",ans[i]);
  96. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注