[BZOJ3337]ORZJRY I

感觉写完这题神清气爽,本来认为平衡树已经属于很复杂的东西了。
强烈推荐写一写这题,写完了就再也不用怕任何数据结构了。
思路很简单,每个块内维护一个\(s\)数组与_s数组。
表示原数组和排完序之后的数组,之后各种操作再打上各种标记。
于是你就轻松愉快 的解决了这道题。
代码:

#include <bits/stdc++.h>
#define il inline
#define gc() getchar()
#define pc putchar
#define isd isdigit
#define set _set
#pragma GCC optimize(2) 
#define max(x,y) (x > y ? x : y)
#define min(x,y) (x < y ? x : y)
const int INF  = 0x7f7f7f7f;
const int _MAX = 1e3 + 10;
const int MAXN = 1e4 + 10;
typedef long long ll;
using namespace std;    
char buf[1<<21],*p1=buf,*p2=buf;
int n,m,i,j,k,opt,bls;
int sta[MAXN];
queue<int> q;
template<typename T> il void read(T& res) {
    res = 0;char c;bool sign = 0;
    for(c = gc();!isd(c);c = gc()) sign |= c == '-';
    for(;isd(c);c = gc()) res = (res << 1) + (res << 3) + (c ^ 48);
    res *= (sign) ? -1 : 1;
    return;
}
il int _abs(int x) {
    return x < 0 ? -x : x;
}
struct Node {
    int s[_MAX],_s[_MAX];
    int size,nxt,rev,add,same;
    ll sum;
    il void clear() {
        size = nxt = rev = add = same =  0;sum = 0ll;
        nxt = -1;
        memset(s,0,sizeof(s));
        memset(_s,0,sizeof(_s));
    }
}t[MAXN]; 
il void _swap(int& x,int& y) {
    x ^= y ^= x ^= y;
}
il int NewNode() {
    int res = q.front();q.pop();return res;
}
il void _del(int num) {
    q.push(num);t[num].clear();return;
}
il void get(int& N,int& now) {
    now = 0;
    while(t[now].nxt != -1 && N > t[now].size) {
        N -= t[now].size;
        now = t[now].nxt;
    }
    return;
}
il void up(int num) {
    if(t[num].rev) {
        t[num].rev = 0;
        for(int i = 1;i <= t[num].size / 2;i++) {
            _swap(t[num].s[i],t[num].s[t[num].size - i + 1]);
        }
    }
    if(t[num].same) {
        for(int i = 1;i <= t[num].size;i++) t[num].s[i] = t[num].same;
        t[num].sum = t[num].same * t[num].size;t[num].same = 0;
    }
    if(t[num].add) {
        for(int i = 1;i <= t[num].size;i++) t[num].s[i] += t[num].add;
        t[num].sum += t[num].add * t[num].size;t[num].add = 0;
    }
    return;
}
il void _set(int num) {
    t[num].sum = 0;
    for(int i = 1;i <= t[num].size;i++) {
        t[num].sum += t[num].s[i];t[num]._s[i] = t[num].s[i];
    }
    sort(t[num]._s + 1,t[num]._s + t[num].size + 1);
    return;
}
il void Merge(int num) {        
    int tmp = t[num].nxt;          
    up(num);up(tmp);
    for(int i = 1;i <= t[tmp].size;i++) {
        t[num].s[++t[num].size] = t[tmp].s[i];      
    }
    t[num].nxt = t[tmp].nxt;
    _del(tmp);set(num);
}
il void _Merge(int num) {
    int now = num;
    while(now != -1) {
        if(t[now].nxt != -1 && t[now].size + t[t[now].nxt].size <= bls) {
            Merge(now);
        }
        now = t[now].nxt;
    }   
    return;
}
il void divide(int num,int pos) {
    up(num);int tmp = NewNode();
    for(int i = pos;i <= t[num].size;i++) {
        t[tmp].s[++t[tmp].size] = t[num].s[i];
    }
    t[tmp].nxt = t[num].nxt;t[num].nxt = tmp;
    t[num].size = max(pos - 1,0);set(tmp);set(num);
} 
il void insert(int pos,int val) {
    int now;pos++;get(pos,now);divide(now,pos);
    t[now].s[++t[now].size] = val;
    set(now);_Merge(now);
}
il void _delete(int pos) {
    int now;get(pos,now);up(now);        
    for(int i = pos;i < t[now].size;i++) {
        t[now].s[i] = t[now].s[i + 1];      
    }                 
    t[now].size--;set(now);_Merge(now);
    return;
}                                           
il void orz(int l,int r,int& _l,int& _r) {
    int pos = l;get(pos,_l);divide(_l,pos);      
    pos = r + 1;get(pos,_r);divide(_r,pos);
    pos = r;get(pos,_r);return;
}
il void reverse(int l,int r) {
    int _l,_r;orz(l,r,_l,_r);
    int p = t[_l].nxt,top = 0;
    while(p != t[_r].nxt) {
        sta[++top] = p;t[p].rev ^= 1;p = t[p].nxt;
    }
    t[sta[1]].nxt = t[_r].nxt;
    for(int i = top;i > 1;i--) t[sta[i]].nxt = sta[i - 1];
    t[_l].nxt = _r;_Merge(_l);return;
}
il void move_kth(int x,int y,int z) {
    int _l,_r,p,_p;
    orz(x,y - z,_l,p);
    orz(y - z + 1,y,p,_r);
    _p = t[_l].nxt;
    t[_l].nxt = t[p].nxt;
    t[p].nxt  = t[_r].nxt;
    t[_r].nxt = _p;
    _Merge(_l);
    return; 
}
il void add(int x,int y,int z) {
    int l,r;orz(x,y,l,r);int p = t[l].nxt;
    while(p != t[r].nxt) {
        t[p].add += z;t[p].sum += z * t[p].size;
        p = t[p].nxt;
    }
    _Merge(l);
    return;
}
il void same(int x,int y,int z) {
    int l,r;orz(x,y,l,r);int p = t[l].nxt;
    while(p != t[r].nxt) {
        t[p].add = 0;t[p].same = z;t[p].sum = t[p].size * z;
        p = t[p].nxt;
    }
    _Merge(l);
    return;
}
il ll sum(int x,int y) {
    int l,r;orz(x,y,l,r);ll res = 0ll,p = t[l].nxt;
    while(p != t[r].nxt) res += t[p].sum,p = t[p].nxt;_Merge(l);
    return res;
}
il int range(int x,int y) {
    int l,r;orz(x,y,l,r);ll Max = -INF,Min = INF;int p = t[l].nxt;
    while(p != t[r].nxt) {
        if(t[p].size) {
            if(t[p].same) {
                Max = max(Max,t[p].add + t[p].same);
                Min = min(Min,t[p].add + t[p].same);         
            } else {                                   
                Max = max(Max,t[p]._s[t[p].size] + t[p].add);
                Min = min(Min,t[p]._s[1] + t[p].add);
            }
        }
        p = t[p].nxt;
    }   
    _Merge(l);return Max - Min;
}
il int near(int x,int y,int z) {
    int l,r;orz(x,y,l,r);int p = t[l].nxt,res = INF;
    while(p != t[r].nxt) {
        if(t[p].same) res = min(res,_abs(t[p].same + t[p].add - z));
        else {
            int tmp = lower_bound(t[p]._s + 1,t[p]._s + t[p].size + 1,z - t[p].add) - t[p]._s;
            if(tmp != t[p].size + 1) res = min(res,_abs(t[p]._s[tmp] + t[p].add - z));
            if(tmp != 1) tmp--,res = min(res,_abs(t[p]._s[tmp] + t[p].add - z)); 
        }
        p = t[p].nxt;
    }
    _Merge(l);return res;
}
il int Min_kth(int x,int y,int z) {
    int l,r;orz(x,y,l,r);int hl = 0,hr = 1e9,res;
    while(hl < hr) {
        int mid = (hl + hr) / 2 + 1,K = 1,p = t[l].nxt;
        while(p != t[r].nxt) {
            if(t[p].same) {
                if(t[p].add + t[p].same < mid) K += t[p].size; 
            } else {
                int x = upper_bound(t[p]._s + 1,t[p]._s + t[p].size + 1,mid - t[p].add - 1) - t[p]._s;
                K += max(x - 1,0);
            }
            p = t[p].nxt;
        }
        if(K <= z) hl = mid;
        else hr = mid - 1;
    }
    _Merge(l);return hl;
}
il int qry_min(int x,int y,int z) {
    int l,r;orz(x,y,l,r);int res = 0,p = t[l].nxt;
    while(p != t[r].nxt) {
        if(t[p].same) {
            if(t[p].same + t[p].add < z) res += t[p].size;
        } else {
            int tmp = upper_bound(t[p]._s + 1,t[p]._s + t[p].size + 1,z - t[p].add - 1) - t[p]._s;
            res += max(tmp - 1,0);
        }
        p = t[p].nxt;
    }
    _Merge(l);return res;
}
int main() {
//  freopen("std1.in","r",stdin);
//  freopen("my1.out","w",stdout);
    read(n);bls = sqrt(n);
    for(int i = 1;i < 10000;i++) q.push(i);t[0].nxt = -1;t[0].size = 0;
    for(int i = 1;i <= n;i++) {
        int x;read(x);insert(i - 1,x);
    }   
    read(m);
    for(int i = 1,x,y,k;i <= m;i++) {
        int opt;read(opt);
        switch(opt) {
            case 1: {read(x);read(y);insert(x,y);break;}
            case 2: {read(x);_delete(x);break;}
            case 3: {read(x);read(y);reverse(x,y);break;}
            case 4: {read(x);read(y);read(k);move_kth(x,y,k);break;}
            case 5: {read(x);read(y);read(k);add(x,y,k);break;}
            case 6: {read(x);read(y);read(k);same(x,y,k);break;}
            case 7: {read(x);read(y);printf("%lld\n",sum(x,y));break;}  
            case 8: {read(x);read(y);printf("%d\n",range(x,y));break;}
            case 9: {read(x);read(y);read(k);printf("%d\n",near(x,y,k));break;}
            case 10: {read(x);read(y);read(k);printf("%d\n",Min_kth(x,y,k));break;}
            case 11: {read(x);read(y);read(k);printf("%d\n",qry_min(x,y,k));break;}     
        }
    }
    return 0;
}
posted @ 2019-03-01 22:57  _connect  阅读(238)  评论(0编辑  收藏  举报
Live2D