Description
“将世界终结前最后的画面,深深刻印进死水般的心海.”
祈愿没有得到回应,雷声冲破云霄,正在祈愿的洛天依受到了极大的打击。
洛天依叹了口气,说:”看来这个世界正如我之前所说的一样,早已失去一切生机”
你沉默了下来,没有说什么话,只是静静地坐在洛天依的身旁,一同观赏这末日之景.
天空被云朵覆盖,一朵具有强大能量的云映入你们的眼帘,这是始云!是抽取世界能量的最重要的一朵云!但是洛天依明显没有破坏这朵云的斗志了,你也只好静静地观赏.
这个世界被吸取的能量从始云开始传递,通过愿望银线输送到各个积雨云上,每朵积雨云即作为能量中转点,又作为能量湮灭点。如此,整片天空构成了一个巨大的能量输送网络。很巧,我们可以用图论中的有向图来描述这个网络.
我们定义始云的编号为1.
对于一朵积雨云y,如果从始云开始到这个点的所有路径都经过了点x,那么我们称x是y的支配云,x支配y,y被x支配。显然一个点的支配云可能有多个且至少有两个。
旁边的洛天依此时非常惊讶,因为她发现不同的积雨云的能量强度不一样!
洛天依用正整数来描述这个能量的强度,同时起名为湮灭能量数.
也就是说在这个云朵湮灭的能量的单位数目.
然而整个网络中的云湮灭的能量数在不断的变化中,变化的情况如下:
C 1 u w有一股能量在云朵u中湮灭了w的能量.
C 2 u w点u支配的所有云朵上都湮灭了w能量
C 3 u w支配点u的所有的云朵上都湮灭了w的能量
“最后一次求你了,为我推演一下这毁灭能量的变化吧.”
洛天依一共有四种请求:
Q 1 u 询问u支配的所有的云朵的湮灭能量数之和.
Q 2 u 询问支配u的所有的云朵的湮灭能量数权值之和.
Q 3 s x1 x2 … xs 询问所有支配了其中任一云朵的云朵的湮灭能量数权值之和.
R k让状态回到k次变化之前.若k大于已经执行的操作数,则视为回到初始状态.
你自然不忍心拒绝洛天依,于是你打算圆满完成这个任务.
n≤50000,q≤100000,∑s≤50000,m≤100000,w≤1000
Solution
见过的最简单的F题[逃]
然而当时打的时候心态爆炸WA就没有调试,现在看来血亏_ (:з」∠) _
我写倍增求LCA,结果写着写着忘了写预处理了QwQ
题解很简单,只要你会支配树就是简单题
Q3的话直接把所有关键点按照dfs序排序然后直接减去所有相邻节点的lca到根的路径上的的权值之和就好了。
Code
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define rep(i,a) for(int i=lst[a];i;i=nxt[i])
using namespace std;
typedef long long ll;
int read() {
char ch;
for(ch=getchar();ch<'0'||ch>'9';ch=getchar());
int x=ch-'0';
for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x;
}
void write(ll x) {
if (!x) {puts("0");return;}
char ch[20];int tot=0;
for(;x;x/=10) ch[++tot]=x%10+'0';
fd(i,tot,1) putchar(ch[i]);
puts("");
}
const int N=5*1e4+5;
typedef vector<int> vec;
#define pb(a) push_back(a)
vec pre[N],dom[N];
int lst[N],nxt[N<<1],t[N<<1],l;
void add(int x,int y) {
t[++l]=y;nxt[l]=lst[x];lst[x]=l;
}
int n,m,x,y,semi[N],idom[N];
int id[N],dfn[N],fa[N],tot;
void dfs(int x) {
dfn[x]=++tot;id[tot]=x;
rep(i,x) {
pre[t[i]].pb(x);
if (!dfn[t[i]]) {
fa[t[i]]=x;
dfs(t[i]);
}
}
}
int father[N],val[N];
int get(int x) {
if (father[x]==x) return x;
int y=get(father[x]);
if (dfn[semi[val[father[x]]]]<dfn[semi[val[x]]]) val[x]=val[father[x]];
return father[x]=y;
}
int smin(int x,int y) {return dfn[x]<dfn[y]?x:y;}
void solve() {
fd(i,tot,2) {
int x=id[i];
if (!pre[x].empty())
fo(j,0,pre[x].size()-1)
if (dfn[pre[x][j]]<dfn[x]) semi[x]=smin(semi[x],pre[x][j]);
else {
get(pre[x][j]);
semi[x]=smin(semi[x],semi[val[pre[x][j]]]);
}
father[x]=fa[x];dom[semi[x]].pb(x);
if (!dom[fa[x]].empty())
fo(j,0,dom[fa[x]].size()-1) {
int v=dom[fa[x]][j];get(v);
int u=val[v];
idom[v]=(dfn[semi[u]]<dfn[semi[v]])?u:fa[x];
}
}
fo(i,2,tot) {
int x=id[i];
if (idom[x]!=semi[x]) idom[x]=idom[idom[x]];
}
}
int size[N],f[N][16],dep[N],son[N],a[N];
int top[N],w[N],cnt,tmp;
void travel(int x,int y) {
int k=0;size[x]=1;f[x][0]=y;dep[x]=dep[y]+1;
rep(i,x)
if (t[i]!=y) {
travel(t[i],x);
if (size[t[i]]>k) k=size[t[i]],son[x]=t[i];
size[x]+=size[t[i]];
}
}
void make(int x,int y) {
top[x]=y;dfn[x]=++cnt;w[cnt]=x;
if (!son[x]) return;
make(son[x],y);
rep(i,x)
if (t[i]!=f[x][0]&&t[i]!=son[x])
make(t[i],t[i]);
}
ll tr[N<<6];
int now,root[N],tag[N<<6],ls[N<<6],rs[N<<6],bl[N<<6];
struct node{int id,v;}b[N];
bool cmp(node x,node y) {return x.id<y.id;}
int newnode(int v,int rt) {
tr[++tmp]=tr[v];tag[tmp]=tag[v];
ls[tmp]=ls[v];rs[tmp]=rs[v];
bl[tmp]=rt;
return tmp;
}
void update(int &v,int l,int r,int z,int rt) {
if (bl[v]!=rt) v=newnode(v,rt);
tr[v]+=(ll)(r-l+1)*z;
tag[v]+=z;
}
void down(int v,int l,int r) {
int mid=l+r>>1;
if (tag[v]) {
update(ls[v],l,mid,tag[v],bl[v]);
update(rs[v],mid+1,r,tag[v],bl[v]);
tag[v]=0;
}
}
void build(int &v,int l,int r) {
v=++tmp;
if (l==r) {tr[v]=a[w[l]];return;}
int mid=l+r>>1;
build(ls[v],l,mid);
build(rs[v],mid+1,r);
tr[v]=tr[ls[v]]+tr[rs[v]];
}
void modify(int &v,int l,int r,int x,int y,int z) {
v=newnode(v,now);
if (l==x&&r==y) {update(v,l,r,z,now);return;}
down(v,l,r);int mid=l+r>>1;
if (y<=mid) modify(ls[v],l,mid,x,y,z);
else if (x>mid) modify(rs[v],mid+1,r,x,y,z);
else modify(ls[v],l,mid,x,mid,z),modify(rs[v],mid+1,r,mid+1,y,z);
tr[v]=tr[ls[v]]+tr[rs[v]];
}
ll query(int v,int l,int r,int x,int y) {
if (!v) return 0;
if (l==x&&r==y) return tr[v];
int mid=l+r>>1;down(v,l,r);
if (y<=mid) return query(ls[v],l,mid,x,y);
else if (x>mid) return query(rs[v],mid+1,r,x,y);
else return query(ls[v],l,mid,x,mid)+query(rs[v],mid+1,r,mid+1,y);
}
ll find(int x) {
ll ans=0;
while (x) {
ans+=query(root[now],1,n,dfn[top[x]],dfn[x]);
x=f[top[x]][0];
}
return ans;
}
int lca(int x,int y) {
if (dep[x]<dep[y]) swap(x,y);
fd(j,15,0) if (dep[f[x][j]]>dep[y]) x=f[x][j];
if (dep[x]!=dep[y]) x=f[x][0];
fd(j,15,0) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
return (x==y)?x:f[x][0];
}
int main() {
n=read();m=read();
fo(i,1,n) a[i]=read();
fo(i,1,m) {
x=read();y=read();
add(x,y);
}
fo(i,1,n) father[i]=val[i]=semi[i]=i;
dfs(1);solve();
fo(i,1,n) lst[i]=0;l=0;
fo(i,2,tot) add(idom[i],i);
travel(1,0);make(1,1);
build(root[0],1,n);
fo(j,1,15)
fo(i,1,n)
f[i][j]=f[f[i][j-1]][j-1];
for(int q=read();q;q--) {
char ch;
for(ch=getchar();ch<'A'||ch>'Z';ch=getchar());
if (ch=='C') {
int opt=read();
root[now+1]=root[now];now++;
if (opt==1) {
int x=read(),y=read();
modify(root[now],1,n,dfn[x],dfn[x],y);
}
if (opt==2) {
int x=read(),y=read();
modify(root[now],1,n,dfn[x],dfn[x]+size[x]-1,y);
}
if (opt==3) {
int x=read(),y=read();
while (x) {
modify(root[now],1,n,dfn[top[x]],dfn[x],y);
x=f[top[x]][0];
}
}
}
if (ch=='Q') {
int opt=read();
if (opt==1) {
int x=read();
write(query(root[now],1,n,dfn[x],dfn[x]+size[x]-1));
}
if (opt==2) {
int x=read();
write(find(x));
}
if (opt==3) {
int sz=read();
fo(i,1,sz) {
b[i].v=read();
b[i].id=dfn[b[i].v];
}
sort(b+1,b+sz+1,cmp);
ll ans=0;
fo(i,1,sz) {
ans+=find(b[i].v);
if (i>1) ans-=find(lca(b[i].v,b[i-1].v));
}
write(ans);
}
}
if (ch=='R') {
int x=read();
now=max(0,now-x);
}
}
return 0;
}