洛谷P3810 陌上花开 CDQ分治(三维偏序)

好,这是一道三维偏序的模板题

当然没那么简单.....

首先谴责洛谷一下:可怜的陌上花开的题面被无情的消灭了:

这么好听的名字#(滑稽)

那么我们看了题面后就发现:这就是一个三维偏序。只不过ans不加在一起,而是加在每朵花内部。

很裸的一道CDQ分治,CDQ一维,sort一维,TreeArray一维,然后就爆0了......

把cmp函数改完备之后还是爆0,为什么呢?

看一下这一组样例:

5 3

1 3 3

3 3 3

3 3 3

3 3 3

3 3 3

看得出来正确答案是1 0 0 0 4

但是我们的程序无情的输出了1 1 1 1 1

这表明了什么?要去重!

就用类似离散化的方式去重,然后就——爆0了!

......

然后发现是代码里一个小细节写错了,害得我调了一晚上...

上代码。

 1 #include <cstdio>
 2 #include <algorithm>
 3 using namespace std;
 4 const int N = 100010,K = 200010;
 5 struct Node
 6 {
 7     int a,b,c,ans,sum;
 8     bool operator==(const Node &x)const
 9     {
10         return (this->a==x.a)&&(this->b==x.b)&&(this->c==x.c);
11     }
12 }node[N];
13 bool cmp_a(Node x,Node y) /// !!!!
14 {
15     if(x.a!=y.a)return x.a<y.a;
16     if(x.b!=y.b)return x.b<y.b;
17     return x.c<y.c;
18 }
19 bool cmp_b(Node x,Node y)
20 {
21     if(x.b!=y.b)return x.b<y.b;
22     return x.c<y.c;
23 }
24 int lowbit(int x){return x&(-x);}
25 int TA[K],n,k;
26 void add(int x,int a)
27 {
28     if(!x) return;
29     for(int i=x;i<=k;i+=lowbit(i)) TA[i]+=a;
30     return;
31 }
32 int getsum(int x)
33 {
34     if(!x)return 0;int ans=0;
35     for(int i=x;i>0;i-=lowbit(i)) ans+=TA[i];
36     return ans;
37 }
38 void merge(int l,int r)
39 {
40     //printf("merge:%d %d\n",l,r);
41     int mid=(l+r)>>1;
42     sort(node+l,node+mid+1,cmp_b);
43     sort(node+mid+1,node+r+1,cmp_b);
44     int i=l,j=mid;
45     while(j<r)
46     {
47         j++;
48         while(node[i].b<=node[j].b&&i<=mid)
49             add(node[i].c,node[i].sum),i++;
50         node[j].ans+=getsum(node[j].c);//printf("node[%d].ans+=%d\n",j,getsum(node[j].c));
51     }
52     for(j=l;j<i;j++) add(node[j].c,-1*node[j].sum);/// !!!!
53     //fill(TA,TA+K,0);
54     return;
55 }
56 void CDQ(int l,int r)
57 {
58     if(l==r) return;
59     int mid=(l+r)>>1;
60     CDQ(l,mid);CDQ(mid+1,r);
61     merge(l,r);
62     return;
63 }
64 int ans[N];
65 int main()
66 {
67     scanf("%d%d",&n,&k);
68     for(int i=1;i<=n;i++) scanf("%d%d%d",&node[i].a,&node[i].b,&node[i].c);
69     sort(node+1,node+n+1,cmp_a);
70     int t=0,c=1;
71     for(int i=2;i<=n+1;i++)/// !!!!!!!
72     {
73         if(node[i]==node[i-1])
74         {
75             c++;
76         }
77         else
78         {
79             node[++t]=node[i-1];
80             node[t].sum=c;
81             c=1;
82         }
83     }
84     //for(int i=1;i<=t;i++) printf("%d %d %d %d\n",node[i].a,node[i].b,node[i].c,node[i].sum);
85     CDQ(1,t);
86     sort(node+1,node+1+t,cmp_a);
87     //for(int i=1;i<=t;i++) printf("%d ",node[i].ans);printf("\n");
88     for(int i=1;i<=t;i++) ans[node[i].ans+node[i].sum-1]+=node[i].sum;///这里加上去掉的重复桦
89     for(int i=1;i<=n;i++) printf("%d\n",ans[i-1]);
90     return 0;
91 }
AC代码:

第一次写CDQ,繁琐的细节好多...

posted @ 2018-04-18 12:41  huyufeifei  阅读(153)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

ReadEra 阅读书籍

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜