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


    【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
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Linux Ctrl+Z的使用方法
    ImageView android:tint
    vim recording的使用方法
    java多态实现原理
    Java 修饰符
    Java 变量类型
    Java 对象和类
    Java内存结构详解
    一维数组
    数组
  • 原文地址:https://www.cnblogs.com/cjyyb/p/8011956.html
Copyright © 2020-2023  润新知