BZOJ 3262(Treap+樹狀陣列)
阿新 • • 發佈:2018-11-29
題面
分析
分三維考慮
對第一維,直接排序
對第二維和第三維,我們這樣考慮
樸素的方法是建k棵Treap,第i棵Treap裡存第二維值為k的第三維數值
每次查詢一組(a,b,c),只要在1~b的Treap裡查詢<=c的數的個數即可
這樣可以保證一定是合法的,因為排序,第一維肯定<=a,因為Treap根據值域建,第二維肯定<=b
又根據平衡樹的性質,第三維肯定<=c
這樣總的時間複雜度是\(O(nk\log n)\),無法接受
我們考慮用樹狀陣列的拆分方法,把一組詢問拆成\(\log k\)組詢問
第i棵Treap儲存的是第二維在${[i- \rm lowbit}(i)+1,i] $之間的三元組的第三維
然後按照樹狀陣列查詢和更新的方法求出答案即可
時間複雜度\(O(n \log n \log k)\)
程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<stack> #define maxn 100005 #define maxv 200005 #define maxs 5000005 #define lson tree[p].l #define rson tree[p].r using namespace std; int n,k; struct node { int l; int r; int val; int dat; int cnt; int size; } tree[maxs]; int tot=0; int root[maxv]; void update(int p) { tree[p].size=tree[lson].size+tree[rson].size+tree[p].cnt; } void zig(int &p) { int q=tree[p].l; tree[p].l=tree[q].r; tree[q].r=p; p=q; update(tree[p].r); update(p); } void zag(int &p) { int q=tree[p].r; tree[p].r=tree[q].l; tree[q].l=p; p=q; update(tree[p].l); update(p); } int New(int val) { tree[++tot].val=val; tree[tot].dat=rand(); tree[tot].cnt=1; tree[tot].size=1; return tot; } void insert(int &p,int val) { if(p==0) { p=New(val); return; } if(val==tree[p].val) { tree[p].cnt++; update(p); return; } if(val<tree[p].val) { insert(lson,val); if(tree[lson].dat>tree[p].dat) zig(p); } else { insert(rson,val); if(tree[rson].dat>tree[p].dat) zag(p); } update(p); } int get_rank_by_val(int p,int val) { if(p==0) return 0; if(val==tree[p].val) { return tree[lson].size+tree[p].cnt; } if(val<tree[p].val) { return get_rank_by_val(lson,val); } return get_rank_by_val(rson,val)+tree[lson].size+tree[p].cnt; } inline int lowbit(int x) { return x&-x; } void update(int x,int v){ while(x<=n){ // printf(" tree %d, update %d\n",x,v); insert(root[x],v); x+=lowbit(x); } } int query(int x,int v){ int level=0; while(x){ // printf(" tree %d, query %d\n",x,v ); level+=get_rank_by_val(root[x],v); x-=lowbit(x); } return level; } struct flower{ int s; int c; int m; friend bool operator == (flower a,flower b){ return a.s==b.s&&a.c==b.c&&a.m==b.m; } friend bool operator < (flower a,flower b){ if(a.s==b.s){ if(a.c==b.c) return a.m<b.m; else return a.c<b.c; }else{ return a.s<b.s; } } }a[maxn]; int level[maxn]; int cnt[maxn]; stack<int>s; int main() { scanf("%d %d",&n,&k); for(int i=1;i<=n;i++){ scanf("%d %d %d",&a[i].s,&a[i].c,&a[i].m); } sort(a+1,a+1+n); for(int i=1;i<=n;i++){ if(a[i]==a[i+1]) s.push(i); else{ level[i]=query(a[i].c,a[i].m); while(!s.empty()){ level[s.top()]=level[i]; s.pop(); } } update(a[i].c,a[i].m); } for(int i=1;i<=n;i++){ cnt[level[i]]++; } for(int i=0;i<=n-1;i++){ printf("%d\n",cnt[i]); } }