1. 程式人生 > >BZOJ 3262(Treap+樹狀陣列)

BZOJ 3262(Treap+樹狀陣列)

題面

傳送門

分析

分三維考慮

對第一維,直接排序

對第二維和第三維,我們這樣考慮

樸素的方法是建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]);
    }
}