遥想当年,xuruifan想用线段树套可持久化treap日这题,结果最后也只得了80分……
为了不步xuruifan的后尘,我orz了题解
我们可以用一个线段树来维护当前的所有栈顶元素,支持区间覆盖和区间求和
然后我们维护一个主席树,维护每个版本的时候的栈顶元素,并维护每个栈顶元素被加入是在哪个版本,这样在区间压栈的时候我们可以区间赋值,在单点弹栈的时候我们可以先查到栈顶元素被加入的版本,然后在前一个版本即可查到弹出之后的栈顶,在主席树和线段树中修改即可
1A了,好爽啊!
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<map>
#include<set>
#include<bitset>
#include<queue>
#include<stack>
using namespace std;
#define MAXN 500010
#define MAXM 40000010
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-8
#define ll long long
struct data{
int v;
int fro;
int t;
data(){
}
data(int _v,int _fro,int _t){
v=_v;
fro=_fro;
t=_t;
}
friend bool operator <(data x,data y){
return x.t>y.t;
}
};
int n,m,typ;
int la;
int son[MAXM][2];
data v[MAXM];
int tot;
int sum[MAXN<<2],col[MAXN<<2];
int rt[MAXN];
void change(int &x,int xx,int y,int z,int l,int r,data cv){
x=++tot;
memcpy(son[x],son[xx],sizeof(son[x]));
v[x]=v[xx];
if(y==l&&z==r){
v[x]=min(v[x],cv);
return ;
}
int mid=y+z>>1;
if(r<=mid){
change(son[x][0],son[xx][0],y,mid,l,r,cv);
}else if(l>mid){
change(son[x][1],son[xx][1],mid+1,z,l,r,cv);
}else{
change(son[x][0],son[xx][0],y,mid,l,mid,cv);
change(son[x][1],son[xx][1],mid+1,z,mid+1,r,cv);
}
}
data ask(int x,int y,int z,int p){
data re=v[x];
if(y==z||!x){
return re;
}
int mid=y+z>>1;
if(p<=mid){
re=min(re,ask(son[x][0],y,mid,p));
}else{
re=min(re,ask(son[x][1],mid+1,z,p));
}
return re;
}
inline void toch(int x,int y,int z,int cv){
sum[x]=cv*(z-y+1);
col[x]=cv;
}
inline void pd(int x,int y,int z){
if(col[x]){
int mid=y+z>>1;
toch(x<<1,y,mid,col[x]);
toch(x<<1|1,mid+1,z,col[x]);
col[x]=0;
}
}
inline void ud(int x){
sum[x]=sum[x<<1]+sum[x<<1|1];
}
void Change(int x,int y,int z,int l,int r,int cv){
if(y==l&&z==r){
toch(x,y,z,cv);
return ;
}
pd(x,y,z);
int mid=y+z>>1;
if(r<=mid){
Change(x<<1,y,mid,l,r,cv);
}else if(l>mid){
Change(x<<1|1,mid+1,z,l,r,cv);
}else{
Change(x<<1,y,mid,l,mid,cv);
Change(x<<1|1,mid+1,z,mid+1,r,cv);
}
ud(x);
}
int Ask(int x,int y,int z,int l,int r){
if(y==l&&z==r){
return sum[x];
}
pd(x,y,z);
int mid=y+z>>1;
if(r<=mid){
return Ask(x<<1,y,mid,l,r);
}else if(l>mid){
return Ask(x<<1|1,mid+1,z,l,r);
}else{
return Ask(x<<1,y,mid,l,mid)+Ask(x<<1|1,mid+1,z,mid+1,r);
}
}
int now=0;
int main(){
int o,x,y,z;
scanf("%d%d%d",&n,&m,&typ);
while(m--){
now++;
rt[now]=rt[now-1];
scanf("%d",&o);
if(o==1){
scanf("%d%d",&x,&y);
x=((ll)la*typ+x)%n+1;
y=((ll)la*typ+y)%n+1;
if(x>y){
swap(x,y);
}
printf("%d\n",la=Ask(1,1,n,x,y));
}
if(o==2){
scanf("%d",&x);
x=((ll)la*typ+x)%n+1;
data t=ask(rt[now],1,n,x);
t=ask(rt[t.fro],1,n,x);
t.t=now;
change(rt[now],rt[now],1,n,x,x,t);
Change(1,1,n,x,x,t.v);
}
if(o==3){
scanf("%d%d%d",&x,&y,&z);
x=((ll)la*typ+x)%n+1;
y=((ll)la*typ+y)%n+1;
if(x>y){
swap(x,y);
}
change(rt[now],rt[now],1,n,x,y,data(z,now-1,now));
Change(1,1,n,x,y,z);
}
}
return 0;
}
/*
10 10 0
3 1 5 3
1 1 6
3 1 7 1
1 1 9
1 1 6
3 1 5 2
1 3 6
1 3 9
3 1 7 6
2 1
*/