zoukankan      html  css  js  c++  java
  • 打铁选手的 CDQ分治 刷题记录

    BZOJ3262

    • 模板题,三位偏序。
    • 注意第一维排完序之后再给二三维排序的时候还是要考虑下第一维的:如果二三维都相等的话第一维小的要在前面
    • 代码:
       1 #include <bits/stdc++.h>
       2 #define nmax 1000100
       3 #define lowbit(x) x&(-x)
       4  
       5 using namespace std;
       6 struct point{
       7     int x,y,z;
       8     bool operator == (const point& c) const { return (c.x==x)&&(c.y==y)&&(c.z==z); }
       9 };
      10 point in[nmax],a[nmax];
      11 int n,k;
      12 int p[nmax],c[nmax]={0},v[nmax]={0},an[nmax]={0},fa[nmax]={0};
      13  
      14 bool cmp1(point c,point b){
      15     if(c.x==b.x) return (c.y==b.y)?(c.z<b.z):(c.y<b.y);
      16     else return c.x<b.x;
      17 }
      18  
      19 bool cmp2(int b,int c){
      20     if(a[b].y==a[c].y) return (a[b].z==a[c].z)?(a[b].x<a[c].x):(a[b].z<a[c].z);
      21     return a[b].y<a[c].y;  //第二次排序的时候也是要考虑a的
      22 }
      23  
      24 inline void addv(int x,int t){
      25     while(x<=k){ c[x]+=t; x+=lowbit(x); }
      26 }
      27  
      28 inline int f(int x){
      29     int ans=0;
      30     while(x>0) { ans+=c[x]; x-=lowbit(x); }
      31     return ans;
      32 }
      33  
      34 void solve(int l,int r){
      35     if(l==r) { an[l]+=(v[l]-1); return; }
      36     int ans=0,mid=(l+r)/2;
      37     for (int i=l; i<=r; i++) p[i]=i;
      38     sort(p+l,p+r+1,cmp2);
      39     for (int i=l; i<=r; i++) {
      40         int id=p[i];
      41         if(id<=mid) addv(a[id].z,v[id]); //在左边
      42         else {
      43                 an[id]+=f(a[id].z);   //在右边
      44  //               printf("now an[%d]=%d 
      ",id,an[id]);
      45         }
      46     }
      47     //清空树状数组
      48     for (int i=l; i<=r; i++) {
      49             int id=p[i];
      50             if(id<=mid) addv(a[id].z,(-1)*v[id]);
      51     }
      52     solve(l,mid);
      53     solve(mid+1,r);
      54 }
      55  
      56 int main(){
      57     scanf("%d%d",&n,&k);
      58     for (int i=1; i<=n; i++) scanf("%d%d%d",&in[i].x,&in[i].y,&in[i].z);
      59     sort(in+1,in+n+1,cmp1);
      60     //去重
      61     int cnt=0,i=1,j=2;
      62     while (i<=n){
      63         a[++cnt]=in[i];
      64         v[cnt]=1;
      65         while(in[i]==in[j]) { j++; v[cnt]++; }
      66         i=j; j++;
      67     }
      68     //去重 over 要处理的数组是a
      69     solve(1,cnt);
      70     for (int i=1; i<=cnt; i++) fa[an[i]]+=v[i];
      71     for (int i=0; i<n; i++) printf("%d
      ",fa[i]);
      72     return 0;
      73 }
      030
  • 相关阅读:
    文艺平衡树
    [BJOI2010] 严格次小生成树
    BZOJ3864 hero meet devil
    [NOI2010]能量采集(莫比乌斯反演)
    陌上花开(三维偏序)(cdq分治)
    树状数组套trie 模板
    SDOI2010粟粟的书架
    OI计算几何 简单学习笔记
    OI知识点|NOIP考点|省选考点|教程与学习笔记合集
    悬线法学习笔记
  • 原文地址:https://www.cnblogs.com/jiecaoer/p/11322495.html
Copyright © 2011-2022 走看看