• bzoj 3262 陌上花开


    bzoj 3262 陌上花开

    • (CDQ) 分治模板题.先将所有点按照 (a) 的大小排序,然后分治处理.
    • 处理区间 ([l,r]) 时,可以递归解决 ([l,mid],[mid+1,r]) 两个区间内的贡献,于是只需要处理区间 ([l,mid]) 对区间 ([mid+1,r]) 的贡献.
    • 把这些点全部按照 (b) 的大小排序,这样前两维都有序了.然后遍历一次.对于原来是左边的点,就在 (c) 的位置加 (1) ,原来是右边的点,就询问一次 ([1,c]) 加了几次.用树状数组维护一下.
    • 思路还是比较简单的?然而此题细节较多...
    1. 有三维全部相同的点.直接做的话,相同点彼此间贡献就会算漏.解决方法是在读入后手动去重,并且记录每个点的个数.这样修改的时候加的权值就为个数,最后统计答案的时候也要考虑相同的点个数.
    2. 一定要排全序,否则会算漏???
    3. 清空树状数组的时候别傻不拉几地 (fill/memset) ,正确姿势是把改过的地方记下来,结束的时候改回去.最大的几组数据常数大概差了 (10sim 30) 倍?

    (upd:) 每次都直接清空复杂度都是假的...我咋这么弱智...

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
    	int out=0,fh=1;
    	char jp=getchar();
    	while ((jp>'9'||jp<'0')&&jp!='-')
    		jp=getchar();
    	if (jp=='-')
    		fh=-1,jp=getchar();
    	while (jp>='0'&&jp<='9')
    		out=out*10+jp-'0',jp=getchar();
    	return out*fh;
    }
    const int MAXN=1e5+10;
    int T;
    struct node
    {
    	int a,b,c,id,cnt,f;
    	void init()
    	{
    		a=read(),b=read(),c=read();
    		cnt=1;
    	}
    	bool operator < (const node &rhs) const
    	{
    		if(T==1)
    			{
    				if(a!=rhs.a)
    					return a<rhs.a;
    				if(b!=rhs.b)
    					return b<rhs.b;
    				return c<rhs.c;
    			}
    		if(b!=rhs.b)
    			return b<rhs.b;
    		if(c!=rhs.c)
    			return c<rhs.c;
    		return a<rhs.a;
    	}
    } q[MAXN],oq[MAXN];
    int n,k;
    int bit[MAXN<<1];
    int ans[MAXN],times[MAXN];
    #define lowbit(x) x&(-x)
    void add(int x,int c)
    {
    	for(; x<=k; x+=lowbit(x))
    		bit[x]+=c;
    }
    int query(int x)
    {
    	int s=0;
    	for(; x; x-=lowbit(x))
    		s+=bit[x];
    	return s;
    }
    node Q[MAXN];
    int tp,pos[MAXN],v[MAXN];
    void solve(int l,int r)
    {
    	if(l==r)
    		return;		
    	int mid=(l+r)>>1;
    	solve(l,mid);
    //	fill(bit,bit+1+k,0);
    	tp=0;
    	int cnt=0;
    	for(int i=l; i<=r; ++i)
    		{
    			Q[++cnt]=q[i];
    			Q[cnt].f=(i<=mid)?1:0;
    		}
    	T=2;
    	sort(Q+1,Q+1+cnt);
    	for(int i=1; i<=cnt; ++i)
    		{
    			if(Q[i].f)
    				{
    					add(Q[i].c,Q[i].cnt);
    					++tp;
    					pos[tp]=Q[i].c,v[tp]=Q[i].cnt;
    				}
    			else
    				{
    					int id=Q[i].id;
    					ans[id]+=query(Q[i].c);
    				}
    		}
    	for(int i=1;i<=tp;++i)
    		add(pos[i],-v[i]);
    	solve(mid+1,r);
    }
    int tot[MAXN];
    int main()
    {
    	n=read(),k=read();
    	for(int i=1; i<=n; ++i)
    		oq[i].init();
    	T=1;
    	int N=n;
    	int rp=0;
    	sort(oq+1,oq+1+n);
    	int fst=0;
    	for(int i=1; i<=n; ++i)
    		{
    			if(i==1 || oq[i].a!=oq[i-1].a || oq[i].b!=oq[i-1].b || oq[i].c!=oq[i-1].c)
    				{
    					if(fst)
    						{
    							q[++rp]=oq[fst];
    							q[rp].id=rp;
    							times[rp]=q[rp].cnt;
    						}
    					fst=i;
    				}
    			else
    				++oq[fst].cnt;
    		}
    	q[++rp]=oq[fst],q[rp].id=rp;
    	times[rp]=q[rp].cnt;
    	n=rp;
    	solve(1,n);
    	for(int i=1; i<=n; ++i)
    		tot[ans[i]+times[i]-1]+=times[i];
    	for(int i=0; i<N; ++i)
    		printf("%d
    ",tot[i]);
    	return 0;
    }
    
  • 相关阅读:
    【转载】python自动提取文本中的时间(包含中文日期)
    【转载】PCA降维
    【转载】从头到尾彻底理解KMP算法
    【转载】傅里叶分析之掐死教程(完整版)更新于2014.06.06(Heinrich)
    【转载】白素贞的身世之谜
    React 路由参数改变页面不刷新问题
    前端学习资源笔记
    Nginx配置网站默认https
    基于Docker搭建大数据集群(一)Docker环境部署
    基于Docker搭建大数据集群(三)Hadoop部署
  • 原文地址:https://www.cnblogs.com/jklover/p/10593263.html
Copyright © 2020-2023  润新知