简单模板题:6121. 【GDOI2019模拟2019.4.13】数据结构
首先建树,一层按x二分,一层按y二分交替。
用algorithm中的nth_element(开始,中间,结束(开),比较函数)就可以把点分成两边。但是两边是乱序的。这是线性的.
然后把每个点控制的矩形区域更新上来,接下来就类似二维线段树了。
据说询问一个矩阵是 O ( n 0.5 ) O(n^{0.5}) O(n0.5)的。证明不显然
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=4e5+10;
int n,m;
int opt[N][3],T;
int c[N][2],dep[N];
int a[N];
ll pre[N];
struct point{int x,y;}p[N];
bool operator == (const point &a,const point &b) {
return a.x == b.x && a.y == b.y;
}
struct node {
int lx,ly,rx,ry,dep;
ll v = 0,hismi = 0,tag = 0,mitag=0;
node(int lxx=0,int lyy=0,int rxx=0,int ryy=0,int d=0){
lx=lxx,ly=lyy,rx=rxx,ry=ryy,dep=d;
v=0,tag=0;
}
void tagge(ll vv,ll mi=0){
mitag = min(mitag, tag + mi);
tag += vv;
}
} t[N];
void pushdown(int x){
if(c[x][0]) t[c[x][0]].tagge(t[x].tag,t[x].mitag);
if(c[x][1]) t[c[x][1]].tagge(t[x].tag,t[x].mitag);
t[x].hismi = min(t[x].hismi, t[x].v + t[x].mitag);
t[x].v += t[x].tag;
t[x].tag=0;
t[x].mitag=0;
}
bool cmpx(const point &a,const point &b) {
return a.x < b.x || a.x == b.x && a.y < b.y;
}
bool cmpy(const point &a,const point &b) {
return a.y < b.y || a.y == b.y && a.x < b.x;
}
int tot;
int build(int L,int R,int dep){
int mid=L+R>>1,no=++tot;
t[no].dep=dep;
if(L!=R) {
if(dep&1){
nth_element(p+L,p+mid,p+R+1,cmpx);
c[no][0]=build(L,mid,dep+1);
c[no][1]=build(mid+1,R,dep+1);
}else{
nth_element(p+L,p+mid,p+R+1,cmpy);
c[no][0]=build(L,mid,dep+1);
c[no][1]=build(mid+1,R,dep+1);
}
t[no].lx=min(t[c[no][0]].lx,t[c[no][1]].lx);
t[no].ly=min(t[c[no][0]].ly,t[c[no][1]].ly);
t[no].rx=max(t[c[no][0]].rx,t[c[no][1]].rx);
t[no].ry=max(t[c[no][0]].ry,t[c[no][1]].ry);
} else {
t[no]=node(p[mid].x,p[mid].y,p[mid].x,p[mid].y,dep);
}
return no;
}
int tlx,trx,tly,ttry;
ll v;
void fz(int vv,int lx,int rx,int ly,int ry){
v=vv;
tlx=lx,trx=rx,tly=ly,ttry=ry;
}
#define outof(a,b,c,d) ((b) < (c) || (a) > (d))
void modify(int w){
if(outof(t[w].lx, t[w].rx, tlx, trx) || outof(t[w].ly, t[w].ry, tly, ttry))return;
if(tlx <= t[w].lx && t[w].rx <= trx && tly <= t[w].ly && t[w].ry <= ttry) {
t[w].tagge(v,v);
return;
}
pushdown(w);
if(c[w][0])modify(c[w][0]);
if(c[w][1])modify(c[w][1]);
}
ll query(int w,int tx,int ty){
pushdown(w);
if(t[w].lx > tx || t[w].rx < tx || t[w].ly > ty || t[w].ry < ty){
return 0;
}
if(t[w].lx == t[w].rx && t[w].ly == t[w].ry){
return t[w].hismi;
}
return min(query(c[w][0],tx,ty),query(c[w][1],tx,ty));
}
int root;
int main(){
t[0]=node(1e8,1e8,0,0);
freopen("ds.in","r",stdin);
freopen("ds.out","w",stdout);
cin>>n>>m;
for(int i=1;i<=n;i++)scanf("%d",&a[i]),pre[i]=pre[i-1]+a[i];
for(int i=1;i<=m;i++){
for(int j=0;j<3;j++)
scanf("%d",&opt[i][j]);
if(opt[i][0]==2){
p[++T]=(point){opt[i][1],opt[i][2]};
}else{
int x = opt[i][1];
opt[i][2] = opt[i][2] - a[x];
a[x] += opt[i][2];
}
}
sort(p+1,p+1+T,cmpx);
T = unique(p+1,p+1+T) - p - 1;
root = build(1,T,1);
for(int i=1;i<=m;i++){
if(opt[i][0] == 1) {
fz(opt[i][2], 1, opt[i][1], opt[i][1], n);
modify(root);
} else {
printf("%lld\n",pre[opt[i][2]] - pre[opt[i][1] - 1] + query(root, opt[i][1], opt[i][2]));
}
}
}