[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;
}