卧薪尝胆,厚积薄发。
UNR1 火车管理
Date: Sat Jan 19 07:45:06 CST 2019 In Category: NoCategory

Description:

$n$ 个栈,支持区间压数,区间栈顶求和,单点弹数。
$1\leqslant n\leqslant 5\times 10^5$

Solution:

发现最难做的就是单点弹栈,但是我们可以把这个理解成恢复到压栈之前的版本,于是用主席树维护历史版本,每次在上一个版本那里查就行了,主席树不维护值而是维护版本号。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n,m,ty;
#define MAXN 500010
#define INF 0x3f3f3f3f
typedef long long ll;
int val[MAXN];
namespace ST
{
struct node
{
int lc,rc;
ll sum,tag;
node(){sum = 0;tag = -INF;}
}t[MAXN << 1];
int ptr = 0;
int newnode(){return ++ptr;}
int root;
#define mid ((l + r) >> 1)
void build(int &rt,int l,int r)
{
rt = newnode();
if(l == r)return;
build(t[rt].lc,l,mid);
build(t[rt].rc,mid + 1,r);
return;
}
void pushdown(int rt,int l,int r)
{
if(t[rt].tag == -INF)return;
int ll = l,lr = mid,rl = mid + 1,rr = r;
t[t[rt].lc].sum = t[rt].tag * (lr - ll + 1);t[t[rt].lc].tag = t[rt].tag;
t[t[rt].rc].sum = t[rt].tag * (rr - rl + 1);t[t[rt].rc].tag = t[rt].tag;
t[rt].tag = -INF;
return;
}
void change(int rt,int L,int R,int k,int l,int r)
{
if(L <= l && r <= R)
{
t[rt].tag = k;t[rt].sum = (r - l + 1) * k;
return;
}
pushdown(rt,l,r);
if(L <= mid)change(t[rt].lc,L,R,k,l,mid);
if(R > mid)change(t[rt].rc,L,R,k,mid + 1,r);
t[rt].sum = t[t[rt].lc].sum + t[t[rt].rc].sum;
return;
}
ll query(int rt,int L,int R,int l,int r)
{
if(L <= l && r <= R)return t[rt].sum;
pushdown(rt,l,r);
ll res = 0;
if(L <= mid)res += query(t[rt].lc,L,R,l,mid);
if(R > mid)res += query(t[rt].rc,L,R,mid + 1,r);
return res;
}
#undef mid
}
namespace PT
{
struct node
{
int lc,rc;
int tag;
node(){tag = 0;}
}t[MAXN * 30];
int ptr = 0;
int newnode(){return ++ptr;}
int root[MAXN];
#define mid ((l + r) >> 1)
void build(int &rt,int l,int r)
{
rt = newnode();
if(l == r)return;
build(t[rt].lc,l,mid);
build(t[rt].rc,mid + 1,r);
return;
}
void pushdown(int rt)
{
if(t[rt].tag != -INF)
{
int k;
k = newnode();t[k] = t[t[rt].lc];t[rt].lc = k;t[t[rt].lc].tag = t[rt].tag;
k = newnode();t[k] = t[t[rt].rc];t[rt].rc = k;t[t[rt].rc].tag = t[rt].tag;
t[rt].tag = -INF;
}
return;
}
void add(int &rt,int L,int R,int v,int l,int r)
{
int k = newnode();t[k] = t[rt];rt = k;
if(L <= l && r <= R)
{
t[rt].tag = v;
return;
}
pushdown(rt);
if(L <= mid)add(t[rt].lc,L,R,v,l,mid);
if(R > mid)add(t[rt].rc,L,R,v,mid + 1,r);
return;
}
int query(int rt,int p,int l,int r)
{
if(l == r)return t[rt].tag;
pushdown(rt);
if(p <= mid)return query(t[rt].lc,p,l,mid);
else return query(t[rt].rc,p,mid + 1,r);
}
#undef mid
}
int main()
{
scanf("%d%d%d",&n,&m,&ty);
int opt,l,r,x;
int tim = 0;
ST::build(ST::root,1,n);
PT::build(PT::root[0],1,n);
int l_,r_;
ll lastans = 0;
for(int i = 1;i <= m;++i)
{
scanf("%d",&opt);
if(opt == 1)
{
scanf("%d%d",&l,&r);
l_ = (l + lastans * ty) % n + 1;
r_ = (r + lastans * ty) % n + 1;
l = min(l_,r_);r = max(l_,r_);
printf("%lld\n",lastans = ST::query(ST::root,l,r,1,n));
}
if(opt == 2)
{
scanf("%d",&l);
l = (l + lastans * ty) % n + 1;
int t = PT::query(PT::root[tim],l,1,n);
--t;
int v = PT::query(PT::root[t],l,1,n);
++tim;
PT::root[tim] = PT::root[tim - 1];
PT::add(PT::root[tim],l,l,v,1,n);
ST::change(ST::root,l,l,val[v],1,n);
}
if(opt == 3)
{
scanf("%d%d%d",&l,&r,&x);
l_ = (l + lastans * ty) % n + 1;
r_ = (r + lastans * ty) % n + 1;
l = min(l_,r_);r = max(l_,r_);
++tim;
PT::root[tim] = PT::root[tim - 1];
val[tim] = x;
PT::add(PT::root[tim],l,r,tim,1,n);
ST::change(ST::root,l,r,x,1,n);
}
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡