BZOJ 3262陌上花开 树状数组套splay

xiaoxiao2021-02-28  67

Description

有n朵花,每朵花有三个属性:花形(s)、颜色(c)、气味(m),又三个整数表示。现要对每朵花评级,一朵花的级别是它拥有的美丽能超过的花的数量。定义一朵花A比另一朵花B要美丽,当且仅当Sa>=Sb,Ca>=Cb,Ma>=Mb。显然,两朵花可能有同样的属性。需要统计出评出每个等级的花的数量。

Input

第一行为N,K (1 <= N <= 100,000, 1 <= K <= 200,000 ), 分别表示花的数量和最大属性值。 以下N行,每行三个整数si, ci, mi (1 <= si, ci, mi <= K),表示第i朵花的属性

Output

包含N行,分别表示评级为0...N-1的每级花的数量。

Sample Input

10 3 3 3 3 2 3 3 2 3 1 3 1 1 3 1 2 1 3 1 1 1 2 1 2 2 1 3 2 1 2 1

Sample Output

3 1 3 0 1 0 1 0 0 1

HINT

1 <= N <= 100,000, 1 <= K <= 200,000

Source

传送门 先用树套树写一遍…… 三维偏序问题,首先其实就是按照第一维排序,然后就可以只看2,3两维了; 对于这样的情况……就用树套树吧…… 用树状数组维护第二维,然后用平衡树维护第三维。。 树状数组和平衡树如何求得排名?。。不多说了吧。 注意不可以啥啥树状数组套树状数组哦…… 树状数组怎么动态开点= = 啊对了对了一定要注意花的属性完全相同的情况…… 如何处理看我主程序吧。。 好吧水题水题…… 不过这个写好常数是真的大…… 改天用cdq分治写一发。。虽然都是两个log级别,,但是后者常数<<树套树呀…… #include<bits/stdc++.h> using namespace std; int read(){ int x=0,f=1;char ch=getchar(); while (ch<'0' || ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int M=100005, KK=200005, N=4000005; int n,K,tot; int Ans[M],root[KK]; struct flower{ int s,c,m; }flo[M]; struct Splay{ int pre,son[2],sz,occ,num; }tree[N]; bool cmp(flower x,flower y){ if (x.s==y.s) if (x.c==y.c) return x.m<y.m; else return x.c<y.c; else return x.s<y.s; } int lowbit(int x){ return x&(-x); } void up(int id){ tree[id].sz=tree[tree[id].son[0]].sz+tree[tree[id].son[1]].sz+tree[id].occ; } void newnode(int id,int x){ tree[id].num=x; tree[id].occ=tree[id].sz=1; tree[id].pre=tree[id].son[0]=tree[id].son[1]=0; } void Rotate(int x){ int y=tree[x].pre,z=tree[y].pre,l,r; if (tree[y].son[0]==x) l=0; else l=1; r=l^1; if (z) if (tree[z].son[0]==y) tree[z].son[0]=x; else tree[z].son[1]=x; tree[x].pre=z; tree[y].pre=x; tree[y].son[l]=tree[x].son[r]; tree[tree[x].son[r]].pre=y; tree[x].son[r]=y; up(y); } void splay(int rt,int x,int goal){ while (tree[x].pre!=goal){ int y=tree[x].pre,z=tree[y].pre; if (z!=goal) if (tree[z].son[0]==y^tree[y].son[0]==x) Rotate(x); else Rotate(y); Rotate(x); } up(x); if (!goal) root[rt]=x; } void insert(int rt,int id,int x){ int u=root[rt],v; while (u){ v=u; if (tree[u].num==x){ tree[u].occ++,tree[u].sz++; splay(rt,u,0); return; } if (tree[u].num>x) u=tree[u].son[0]; else u=tree[u].son[1]; } newnode(id,x); if (!root[rt]) root[rt]=id; else{ tree[id].pre=v; if (tree[v].num>x) tree[v].son[0]=id; else tree[v].son[1]=id; } splay(rt,id,0); } int findminer(int rt,int x){ int u=root[rt],t=0; while (u) if (tree[u].num<=x){ t+=tree[tree[u].son[0]].sz+tree[u].occ; if (tree[u].num==x) return t; u=tree[u].son[1]; } else u=tree[u].son[0]; return t; } void update(int x,int num){ for (int i=x;i<=K;i+=lowbit(i)) insert(i,++tot,num); } int query(int x,int num){ int t=0; for (int i=x;i;i-=lowbit(i)) t+=findminer(i,num); return t; } int main(){ tot=0; memset(Ans,0,sizeof(Ans)); n=read(),K=read(); for (int i=1;i<=n;i++) flo[i].s=read(),flo[i].c=read(),flo[i].m=read(); sort(flo+1,flo+1+n,cmp); int len=1; for (int i=1;i<=n;i++) if (flo[i+1].s==flo[i].s && flo[i+1].c==flo[i].c && flo[i+1].m==flo[i].m){ update(flo[i].c,flo[i].m); len++; continue; } else{ Ans[query(flo[i].c,flo[i].m)]+=len; update(flo[i].c,flo[i].m); len=1; } for (int i=0;i<n;i++) printf("%d\n",Ans[i]); return 0; }
转载请注明原文地址: https://www.6miu.com/read-84606.html

最新回复(0)