BZOJ 3262 陌上花开
2018-01-16 15:40
211 查看
题目传送门
权限题就不放题目描述了思路
不会CDQ分治,只能写树套树了……一维排序,二维线段树,三维splay,注意两朵花相同的情况要特判。
//////////////////////////////////////////////////////////////////////////////////////////
学了一波cdq分治,这道题可以一维排序,二维cdq分治,三维树状数组。
代码(树套树)
#include <cstdio> #include <algorithm> const int maxn=100000; const int maxk=200000; const int maxs=10000000; struct splay_tree { int fa[maxs],son[2][maxs],val[maxs],size[maxs],tot; inline int t(int x) { return son[1][fa[x]]==x; } inline int updata(int x) { return size[x]=size[son[0][x]]+size[son[1][x]]+1; } inline int rotate(int x) { int k=t(x),f=fa[x]; if(fa[f]) { son[t(f)][fa[f]]=x; } fa[x]=fa[f]; if(son[!k][x]) { fa[son[!k][x]]=f; } son[k][f]=son[!k][x]; fa[f]=x; son[!k][x]=f; updata(f); updata(x); return 0; } inline int splay(int &root,int x,int c) { while(fa[x]!=c) { int f=fa[x]; if(fa[f]==c) { rotate(x); } else if(t(x)==t(f)) { rotate(f); rotate(x); } else { rotate(x); rotate(x); } } if(!c) { root=x; } return 0; } inline int ins(int &root,int x) { ++tot; size[tot]=1; fa[tot]=son[0][tot]=son[1][tot]=0; val[tot]=x; if(!root) { root=tot; return 0; } int now=root; while(now) { int k=val[now]<x; if(!son[k][now]) { son[k][now]=tot; fa[tot]=now; break; } now=son[k][now]; } splay(root,now,0); return 0; } int getrank(int now,int x) { if(!now) { return 0; } else if(val[now]<=x) { return size[son[0][now]]+1+getrank(son[1][now],x); } else { return getrank(son[0][now],x); } } }; struct segment_tree { splay_tree st; int root[maxk<<4]; int ins(int now,int left,int right,int pos,int v) { st.ins(root[now],v); if(left==right) { return 0; } int mid=(left+right)>>1; if(pos<=mid) { ins(now<<1,left,mid,pos,v); } else { ins(now<<1|1,mid+1,right,pos,v); } return 0; } int getrank(int now,int left,int right,int askl,int askr,int v) { if((askl<=left)&&(right<=askr)) { return st.getrank(root[now],v); } int mid=(left+right)>>1,res=0; if(askl<=mid) { res+=getrank(now<<1,left,mid,askl,askr,v); } if(mid<askr) { res+=getrank(now<<1|1,mid+1,right,askl,askr,v); } return res; } }; struct data { int s,c,m; bool operator <(const data &other) const { if(s==other.s) { if(c==other.c) { return m<other.m; } return c<other.c; } return s<other.s; } }; data d[maxn+10]; int n,k,ans[maxn+10],sum[maxn+10]; segment_tree st; int main() { scanf("%d%d",&n,&k); for(register int i=1; i<=n; ++i) { scanf("%d%d%d",&d[i].s,&d[i].c,&d[i].m); sum[i]=1; } std::sort(d+1,d+n+1); for(register int i=1; i<=n; ++i) { if((i!=n)&&(d[i].s==d[i+1].s)&&(d[i].c==d[i+1].c)&&(d[i].m==d[i+1].m)) { sum[i+1]+=sum[i]; } else { ans[st.getrank(1,1,k,1,d[i].c,d[i].m)]+=sum[i]; } st.ins(1,1,k,d[i].c,d[i].m); } for(register int i=0; i<n; ++i) { printf("%d\n",ans[i]); } return 0; }
代码(cdq分治)
略显恶心,用了一种叫做pair的东西,然后……#include <cstdio> #include <utility> #include <algorithm> const int maxn=100000; const int maxk=200000; typedef std::pair<int,std::pair<std::pair<int,int>,std::pair<int,int> > > data; //first 第一维 //second.first.first 第二维 //second.first.second 第三维 //second.second.first 数量 //second.second.second 等级 int k; struct tree_array { int c[maxk+10]; inline int lowbit(int x) { return x&(-x); } inline int add(int pos,int x) { while(pos<=k) { c[pos]+=x; pos+=lowbit(pos); } return 0; } inline int sum(int pos) { int res=0; while(pos) { res+=c[pos]; pos-=lowbit(pos); } return res; } }; data d[maxn+10]; tree_array t; bool cmp(data a,data b) { if(a.second.first==b.second.first) { return a.first<b.first; } return a.second.first<b.second.first; } int solve(int l,int r) { if(l==r) { d[l].second.second.second+=d[l].second.second.first-1; return 0; } int mid=(l+r)>>1; solve(l,mid); solve(mid+1,r); std::sort(d+l,d+mid+1,cmp); std::sort(d+mid+1,d+r+1,cmp); int j=l; for(register int i=mid+1; i<=r; ++i) { while((j<=mid)&&(d[j].second.first.first<=d[i].second.first.first)) { t.add(d[j].second.first.second,d[j].second.second.first); ++j; } d[i].second.second.second+=t.sum(d[i].second.first.second); } for(register int i=l; i<j; ++i) { t.add(d[i].second.first.second,-d[i].second.second.first); } return 0; } int n,tot=1,ans[maxn+10]; int main() { scanf("%d%d",&n,&k); for(register int i=1; i<=n; ++i) { scanf("%d%d%d",&d[i].first,&d[i].second.first.first,&d[i].second.first.second); d[i].second.second.first=1; d[i].second.second.second=0; } std::sort(d+1,d+n+1); for(register int i=2; i<=n; ++i) { if((d[i].first==d[i-1].first)&&(d[i].second.first==d[i-1].second.first)) { ++d[tot].second.second.first; } else { ++tot; d[tot]=d[i]; } } solve(1,tot); for(register int i=1; i<=tot; ++i) { ans[d[i].second.second.second]+=d[i].second.second.first; } for(register int i=0; i<n; ++i) { printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- [BZOJ3262]陌上花开
- BZOJ3262 陌上花开
- bzoj3262: 陌上花开
- bzoj 3262: 陌上花开
- BZOJ 3262 陌上花开
- bzoj3262 陌上花开
- BZOJ3262: 陌上花开
- [BZOJ3262] 陌上花开
- BZOJ3262: 陌上花开
- 【bzoj 3262】陌上花开
- bzoj千题计划145:bzoj3262: 陌上花开
- 【bzoj3262】陌上花开
- 【BZOJ】【3262】陌上花开
- 【三维偏序】【分块】bzoj3262 陌上花开
- 「BZOJ」「3262」陌上花开
- [BZOJ3262]陌上花开
- BZOJ 3262 陌上花开
- 【BZOJ】3262: 陌上花开
- 【BZOJ3262】 陌上花开
- BZOJ3262 陌上花开