欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【BZOJ3262】陌上花开(CDQ分治)

程序员文章站 2022-05-14 18:58:56
...

【BZOJ3262】陌上花开(CDQ分治)

题解

原来放过这道题目,题面在这里
树套树的做法也请点上面

这回用CDQ分治做的
其实也很简单,
对于第一维排序之后
显然只有前面的对后面的才会产生贡献

那么,使用CDQ分治
先分,每次递归子问题
合并的时候每次考虑前面的对于后面的贡献
最后统计一下答案

如果在清空树状数组的时候用了memset会TLE

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
using namespace std;
#define MAX 110000
inline int read()
{
    int x=0,t=1;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=-1,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return x*t;
}
int c[MAX<<1],n,K;
int ans[MAX];
struct TNode{int a,b,c,w,ans;}t[MAX];
bool operator<(TNode x,TNode y)
{
    if(x.a!=y.a)return x.a<y.a;
    if(x.b!=y.b)return x.b<y.b;
    return x.c<y.c;
}
bool operator==(TNode a,TNode b)
{
    return a.a==b.a&&a.b==b.b&&a.c==b.c;
}
bool cmp(TNode x,TNode y)
{
    if(x.b!=y.b)return x.b<y.b;
    return x.c<y.c;
}
inline int lowbit(int x){return x&(-x);}
inline void Add(int x,int w){while(x<=K)c[x]+=w,x+=lowbit(x);}
inline int Getsum(int x){int ret=0;while(x)ret+=c[x],x-=lowbit(x);return ret;}
void CDQ(int l,int r)
{
    if(l==r)return;
    int mid=(l+r)>>1;
    CDQ(l,mid);CDQ(mid+1,r);
    sort(&t[l],&t[mid+1],cmp);
    sort(&t[mid+1],&t[r+1],cmp);
    int i=l;
    for(int j=mid+1;j<=r;++j)
    {
        while(i<=mid&&t[j].b>=t[i].b)
        {
            Add(t[i].c,t[i].w);
            ++i;
        }
        t[j].ans+=Getsum(t[j].c);
    }
    for(int j=l;j<i;++j)Add(t[j].c,-t[j].w);
    //memset(c,0,sizeof(c));
}
int main()
{ 
    n=read();K=read();
    for(int i=1;i<=n;++i)
        t[i].a=read(),t[i].b=read(),t[i].c=read();
    sort(&t[1],&t[n+1]);
    int tot=0;
    for(int i=1;i<=n;++i)
    {
        if(t[i]==t[i-1])++t[tot].w;
        else t[++tot]=t[i],t[tot].w++;
    }
    int N=n;
    n=tot;
    CDQ(1,n);       
    for(int i=1;i<=n;++i)ans[t[i].ans+t[i].w-1]+=t[i].w;
    for(int i=0;i<N;++i)
        printf("%d\n",ans[i]);
    return 0;
}