毒瘤出题人,毁我青春,浪费了我一天时间!
首先,我们想到了树套树套树,代码十分短(chang),于是并没人打算这么做。。。$$O(nlog^3n)$$
然后,又有人用了CDQ,一维排序,消除第一维的影响,二维归并,第三位用权值树状数组来统计答案。$$O(nlog^2n)$$
虽然这样确实可以,但是能尽量(装逼)少用就少用数据结构吧。。。
于是我们考虑CDQ套CDQ,没错,两层归并排序!$$O(nlog^2n)$$就是常数大了点$$......$$
无所谓啦,哈哈哈(尴尬不是礼节的微笑)
然后就A啦!
代码:
//这里我写了非递归的归并排序
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{
bool bk;
int aa[4],id;
}a[210000],tmp[210000],tmpp[210000];int n,m,sum,len[3],d[210000],b[210000];
bool cmp(node x,node y){return x.aa[1]<y.aa[1];}
void rework2(int l,int mid,int r)//统计答案
{
len[2]=0;sum=0;
int ll=l,rr=mid+1;
while(ll<=mid && rr<=r)
{
if(tmp[ll].aa[3]<=tmp[rr].aa[3])
{
if(tmp[ll].bk==false)sum++;
tmpp[++len[2]]=tmp[ll++];
}
else
{
if(tmp[rr].bk==true)d[tmp[rr].id]+=sum;
tmpp[++len[2]]=tmp[rr++];
}
}
while(ll<=mid)tmpp[++len[2]]=tmp[ll++];
while(rr<=r)
{
if(tmp[rr].bk==true)d[tmp[rr].id]+=sum;
tmpp[++len[2]]=tmp[rr++];
}
for(int i=l;i<=r;i++)tmp[i]=tmpp[i-l+1];
}
void work2()
{
int lenn=1;
while(lenn<len[1])
{
int x=1;
while(x<=len[1]-(lenn<<1)-1)
{
rework2(x,x+lenn-1,x+(lenn<<1)-1);
x+=(lenn<<1);
}
if(x+lenn<=len[1])rework2(x,x+lenn-1,len[1]);
lenn*=2;
}
}
void rework1(int l,int mid,int r)//第一次归并,不处理结果
{
len[1]=0;
int ll=l,rr=mid+1;
while(ll<=mid && rr<=r)
{
if(a[ll].aa[2]<=a[rr].aa[2])tmp[++len[1]]=a[ll++],tmp[len[1]].bk=false;
else tmp[++len[1]]=a[rr++],tmp[len[1]].bk=true;
}
while(ll<=mid)tmp[++len[1]]=a[ll++],tmp[len[1]].bk=false;
while(rr<=r)tmp[++len[1]]=a[rr++],tmp[len[1]].bk=true;
for(int i=l;i<=r;i++)a[i]=tmp[i-l+1];
}
void work1()//非递归归并排序
{
int lenn=1;
while(lenn<n)
{
int x=1;
while(x<=n-(lenn<<1)-1)
{
rework1(x,x+lenn-1,x+(lenn<<1)-1);
work2();
x+=(lenn<<1);
}
if(x+lenn<=n)/*x+len-1<n*/
{
rework1(x,x+lenn-1,n);
work2();
}
lenn*=2;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].aa[1],&a[i].aa[2],&a[i].aa[3]);
a[i].id=i;//用于找到对应的位置
}
sort(a+1,a+n+1,cmp);
work1();
for(int i=1;i<=n;i++)b[d[i]]++;//统计
for(int i=0;i<n;i++)printf("%d
",b[i]);
return 0;
}
你觉得作者有这么好心给你正确的代码吗?,你觉得这符合出题人的审美吗,你觉得这么裸的题却这么少人出售烤main包夹小绿鸟很正常吗?
瞎扯完毕
于是,膜了好久的题解,终于懂了,╮(╯▽╰)╭。。。
一道不太对劲的点分治。。。点分治不是小于吗喂?啊啊啊啊啊!
没错,问题就出在了等于上面。
如:1,2,1与1,2,3有可能在第一次排序上变成了这样:(1,2,3)在(1,2,1)左边......
于是你修改了排序:
bool cmp(node x,node y){return x.aa[1]==y.aa[1]?(x.aa[2]==y.aa[2]?x.aa[3]<y.aa[3]:x.aa[2]<y.aa[2]):x.aa[1]<y.aa[1];}
但是:
继续膜题解与寄刀片。。。
[终于,功夫不负有心人,终于发现了错误!
]
由于可以等于,则会出现两个相同的三元组,由于CDQ的本质是左边影响右边,所以这两个三元组中预先将左边的三元组加上右边有多少相同的三元组。
如代码:
sort(a+1,a+n+1,cmp);
for(int i=n;i>=2;i--)
{
if(a[i-1].aa[1]==a[i].aa[1] && a[i-1].aa[2]==a[i].aa[2] && a[i-1].aa[3]==a[i].aa[3])d[a[i-1].id]=d[a[i].id]+1;
}
AC代码:
#include<cstdio>
#include<cstring>
#include<algorithm>别想了,想抄代码?
using namespace std;
struct node
{
bool bk;
int aa[4],id;
}a[210000],tmp[210000],tmpp[210000];int n,m,sum,len[3],d[210000],b[210000];
bool cmp(node x,node y){return x.aa[1]==y.aa[1]?(x.aa[2]==y.aa[2]?x.aa[3]<y.aa[3]:x.aa[2]<y.aa[2]):x.aa[1]<y.aa[1];}
void rework2(int l,int mid,int r)
{
len[2]=0;sum=0;
int ll=l,rr=mid+1;
while(ll<=mid && rr<=r)
{
if(tmp[ll].aa[3]<=tmp[rr].aa[3])
{
if(tmp[ll].bk==false)sum++;哈哈,不存在的
tmpp[++len[2]]=tmp[ll++];
}
else
{
if(tmp[rr].bk==true)d[tmp[rr].id]+=sum;
tmpp[++len[2]]=tmp[rr++];
}
}
while(ll<=mid)tmpp[++len[2]]=tmp[ll++];
while(rr<=r)
{
if(tmp[rr].bk==true)d[tmp[rr].id]+=sum;
tmpp[++len[2]]=tmp[rr++];
}
for(int i=l;i<=r;i++)tmp[i]=tmpp[i-l+1];
}
void work2()
{
int lenn=1;
while(lenn<len[1])
{
int x=1;
while(x<=len[1]-(lenn<<1)-1)
{
rework2(x,x+lenn-1,x+(lenn<<1)-1);
x+=(lenn<<1);
}我无处不在
if(x+lenn<=len[1])rework2(x,x+lenn-1,len[1]);
lenn*=2;
}
}
void rework1(int l,int mid,int r)
{
len[1]=0;
int ll=l,rr=mid+1;
while(ll<=mid && rr<=r)
{
if(a[ll].aa[2]<=a[rr].aa[2])tmp[++len[1]]=a[ll++],tmp[len[1]].bk=false;
else tmp[++len[1]]=a[rr++],tmp[len[1]].bk=true;
}
while(ll<=mid)tmp[++len[1]]=a[ll++],tmp[len[1]].bk=false;
while(rr<=r)tmp[++len[1]]=a[rr++],tmp[len[1]].bk=true;
for(int i=l;i<=r;i++)a[i]=tmp[i-l+1];
}
void work1()
{
int lenn=1;
while(lenn<n)
{
int x=1;
while(x<=n-(lenn<<1)-1)
{惩戒那些抄代码的人
rework1(x,x+lenn-1,x+(lenn<<1)-1);
work2();
x+=(lenn<<1);
}
if(x+lenn<=n)/*x+len-1<n*/
{
rework1(x,x+lenn-1,n);
work2();
}
lenn*=2;
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&a[i].aa[1],&a[i].aa[2],&a[i].aa[3]);
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
for(int i=n;i>=2;i--)
{
if(a[i-1].aa[1]==a[i].aa[1] && a[i-1].aa[2]==a[i].aa[2] && a[i-1].aa[3]==a[i].aa[3])d[a[i-1].id]=d[a[i].id]+1;
}
work1();
for(int i=1;i<=n;i++)b[d[i]]++;
for(int i=0;i<n;i++)printf("%d
",b[i]);
return 0;
}抄就抄了,我不管了,CE不怪我