BZOJ 3786星系探索【Splayメンテナンスdfsシーケンス】*
BZOJ 3786星系探索
Description
物理学者のCさんの研究はあるボトルネックに直面している.彼が研究しているのは星系で、この星系にはnつの星があり、そのうち1つの主星(便宜上1番星とデフォルト)があり、残りのすべての星には1つの依存星しかありません.主星は星に依存していない.我々は依存関係を以下のように定義する:星aの依存星がbであれば、星aが星bに依存するb.また、依存関係には伝達性があり、すなわち星aが星bに依存し、星bが星cに依存すると、星aが星cに依存するc.この神秘的な星系の中で、小Cはその性質を初歩的に探究し、星間の依存関係は無環であることを発見した.そして、星aから直接その依存星bに到達するしかないb.各星iにはエネルギー係数wiがある.Cさんは何度か実験をしたいと思っています.i回目の実験では、宇宙船から星diに初期エネルギーが0のエネルギー収集器を打ち上げ、エネルギー収集器は星diから主星に向かい、沿道の各星のエネルギーの一部を収集します.エネルギーを収集するのはこの星のエネルギー係数に等しいです.しかし、星系の構成は変わらないわけではありません.ある時、星系はいくつかの複雑な原因で変化する可能性があります.ある星のエネルギーが励起されると、それに依存するすべての星と彼自身のエネルギー係数が一定値を増加させることがあります.ある時、ある星の依存星が変化する可能性もあるが、変化後に依存関係を満たすには無環である.現在、小Cは時刻0時の各星のエネルギー係数と、各星(主星を除く)の依存星を測定している.次のm時刻、各時刻にいくつかのイベントが発生します.その中でCさんは何回か実験を行うかもしれませんが、彼の実験のたびに、今回の実験エネルギー収集器の最終エネルギーはいくらなのか教えてください.
Input
最初の行の整数nは、星系の星数を表す.次に、n−1行の各行の整数は、それぞれ星2−nの依存星番号を表す.次のn行の整数は、各星の時刻0における初期エネルギー係数wiを表す.次の行には、イベントの合計数を表す整数mがあります.イベントには、次の3つのタイプがあります.(1)「Qdi」は、小Cが実験を開始し、コレクターの初期位置が星diであることを示す.(2)「Cxi yi」は、星xiの依存星が星yiになることを示す.(3)「Fpi qi」は星piのエネルギー励起を表し、定数はqiである.
Output
各イベントタイプQのイベントについて,今回の実験のコレクタの最終エネルギーを表す1行1整数を出力した.
Sample Input
3 1 1 4 5 7 5 Q 2 F 1 3 Q 2 C 2 3 Q 2
Sample Output
9 15 25
HINT
n<=100000,m<=300000, 1=0 w i>=0
tips:
罪悪な卡常、本机の20 s-はBZOJの上でTを要して、BZOJの评测机はジャガイモですか??
BZOJは評価機を交換することを強くお勧めします
どうせコードが正しいんだから、カードとかは関係ないだろう.
まず、この構造がツリー構造であることがわかります.次に、ポイントからルートノードへのパス権値をクエリーし、ノードの父親を変更し、サブツリーに値を追加します.
最初はLCTをやりたかったのですが、LCTを見つけてサブツリー情報をメンテナンスするのは難しそう?
そこで考えてみると、dfsシーケンスの優美な性質を思い浮かべると、求和を接頭辞和に変換し、修正父を区間平行移動に変換し、サブ区間に値を加えて直接入桟ノードと出桟ノードの間の数に値を加えることができる(区間修正?)そしてSplay
非回転Treap定数が大きいと聞いて書いてなかったのですが、まさかSplayも異常かな...
このコードは通れないよ
Description
物理学者のCさんの研究はあるボトルネックに直面している.彼が研究しているのは星系で、この星系にはnつの星があり、そのうち1つの主星(便宜上1番星とデフォルト)があり、残りのすべての星には1つの依存星しかありません.主星は星に依存していない.我々は依存関係を以下のように定義する:星aの依存星がbであれば、星aが星bに依存するb.また、依存関係には伝達性があり、すなわち星aが星bに依存し、星bが星cに依存すると、星aが星cに依存するc.この神秘的な星系の中で、小Cはその性質を初歩的に探究し、星間の依存関係は無環であることを発見した.そして、星aから直接その依存星bに到達するしかないb.各星iにはエネルギー係数wiがある.Cさんは何度か実験をしたいと思っています.i回目の実験では、宇宙船から星diに初期エネルギーが0のエネルギー収集器を打ち上げ、エネルギー収集器は星diから主星に向かい、沿道の各星のエネルギーの一部を収集します.エネルギーを収集するのはこの星のエネルギー係数に等しいです.しかし、星系の構成は変わらないわけではありません.ある時、星系はいくつかの複雑な原因で変化する可能性があります.ある星のエネルギーが励起されると、それに依存するすべての星と彼自身のエネルギー係数が一定値を増加させることがあります.ある時、ある星の依存星が変化する可能性もあるが、変化後に依存関係を満たすには無環である.現在、小Cは時刻0時の各星のエネルギー係数と、各星(主星を除く)の依存星を測定している.次のm時刻、各時刻にいくつかのイベントが発生します.その中でCさんは何回か実験を行うかもしれませんが、彼の実験のたびに、今回の実験エネルギー収集器の最終エネルギーはいくらなのか教えてください.
Input
最初の行の整数nは、星系の星数を表す.次に、n−1行の各行の整数は、それぞれ星2−nの依存星番号を表す.次のn行の整数は、各星の時刻0における初期エネルギー係数wiを表す.次の行には、イベントの合計数を表す整数mがあります.イベントには、次の3つのタイプがあります.(1)「Qdi」は、小Cが実験を開始し、コレクターの初期位置が星diであることを示す.(2)「Cxi yi」は、星xiの依存星が星yiになることを示す.(3)「Fpi qi」は星piのエネルギー励起を表し、定数はqiである.
Output
各イベントタイプQのイベントについて,今回の実験のコレクタの最終エネルギーを表す1行1整数を出力した.
Sample Input
3 1 1 4 5 7 5 Q 2 F 1 3 Q 2 C 2 3 Q 2
Sample Output
9 15 25
HINT
n<=100000,m<=300000, 1
tips:
罪悪な卡常、本机の20 s-はBZOJの上でTを要して、BZOJの评测机はジャガイモですか??
BZOJは評価機を交換することを強くお勧めします
どうせコードが正しいんだから、カードとかは関係ないだろう.
まず、この構造がツリー構造であることがわかります.次に、ポイントからルートノードへのパス権値をクエリーし、ノードの父親を変更し、サブツリーに値を追加します.
最初はLCTをやりたかったのですが、LCTを見つけてサブツリー情報をメンテナンスするのは難しそう?
そこで考えてみると、dfsシーケンスの優美な性質を思い浮かべると、求和を接頭辞和に変換し、修正父を区間平行移動に変換し、サブ区間に値を加えて直接入桟ノードと出桟ノードの間の数に値を加えることができる(区間修正?)そしてSplay
非回転Treap定数が大きいと聞いて書いてなかったのですが、まさかSplayも異常かな...
このコードは通れないよ
#include
using namespace std;
#define N 200010
#define LL long long
#define pi pair
inline int read(){
int ans=0,w=1;char c=getchar();
while(!isdigit(c)&&c!='-')c=getchar();
if(c=='-')w=-1,c=getchar();
while(isdigit(c))ans=(ans<<1)+(ans<<3)+c-'0',c=getchar();
return ans*w;
}
inline void print(LL x){
if(x<0){putchar('-');x=-x;}
if(x>9)print(x/10);
putchar((x-(x/10)*10)+'0');
}
struct Edge{int v,next;}E[N];
int head[N]={0},tot=0;
int n,q,id[N],dfn=0;
int w[N];
pi st[N];
inline void add(int u,int v){
E[++tot]=(Edge){v,head[u]};
head[u]=tot;
}
inline void dfs(int u,int fa){
id[++dfn]=u;
st[dfn]=(pi){w[u],1};
for(int i=head[u];i;i=E[i].next)
if(E[i].v!=fa)dfs(E[i].v,u);
id[++dfn]=u+n;
st[dfn]=(pi){-w[u],-1};
}
int root,fa[N],son[N][2],cnt=0;
int tag[N],siz[N],num[N],typ[N];
LL sum[N],val[N];
inline void pushup(int t){
sum[t]=sum[son[t][0]]+sum[son[t][1]]+val[t];
siz[t]=siz[son[t][0]]+siz[son[t][1]]+1;
num[t]=num[son[t][0]]+num[son[t][1]]+typ[t];
}
inline void pushnow(int t,LL vl){
tag[t]+=vl;
if(typ[t]>0)val[t]+=vl;
else val[t]-=vl;
sum[t]+=vl*num[t];
}
inline void pushdown(int t){
if(fa[t])pushdown(fa[t]);
if(tag[t]){
pushnow(son[t][0],tag[t]);
pushnow(son[t][1],tag[t]);
tag[t]=0;
}
}
inline bool Son(int t){return son[fa[t]][1]==t;}
inline void rotate(int t){
int f=fa[t],g=fa[f];
bool a=Son(t),b=a^1;
if(g)son[g][Son(f)]=t;fa[t]=g;
son[f][a]=son[t][b];fa[son[f][a]]=f;
son[t][b]=f;fa[f]=t;
pushup(f);pushup(t);
}
inline void splay(int t,int tp){
if(!t)return;
pushdown(t);
while(fa[t]!=tp){
int f=fa[t];
if(fa[f]!=tp){
if(Son(t)^Son(f))rotate(t);
else rotate(f);
}
rotate(t);
}
if(!tp)root=t;
}
inline int build(int l,int r){
if(l>r)return 0;
int mid=(l+r)>>1,t=id[mid];
val[t]=sum[t]=st[mid].first;
num[t]=typ[t]=st[mid].second;
siz[t]=1;tag[t]=0;
if(l==r)return t;
fa[son[t][0]=build(l,mid-1)]=t;
fa[son[t][1]=build(mid+1,r)]=t;
pushup(t);
return t;
}
inline int pre(int pos){
int t=son[pos][0];
while(son[t][1])t=son[t][1];
return t;
}
inline int nxt(int pos){
int t=son[pos][1];
while(son[t][0])t=son[t][0];
return t;
}
inline void modify(int l,int r,LL vl){
int ll=pre(l),rr=nxt(r);
splay(ll,0);
splay(rr,root);
pushnow(son[son[root][1]][0],vl);
}
inline LL query(int pos){
splay(pos,0);
return sum[son[pos][0]]+val[pos];
}
inline void change(int pos,int father){
int lx=pre(pos),rx=nxt(pos+n);
splay(lx,0);
splay(rx,lx);
int t=son[rx][0];
fa[t]=0;son[rx][0]=0;
int lf=nxt(father);
splay(father,0);
splay(lf,father);
son[lf][0]=t;fa[t]=lf;
pushup(lf);
pushup(father);
}
int main(){
n=read();
for(int i=2;i<=n;i++){
int x=read();
add(i,x);add(x,i);
}
for(int i=1;i<=n;i++)w[i]=read();
dfs(1,0);
id[0]=n*2+1;st[0]=(pi){0,1};
id[dfn+1]=n*2+2;st[dfn+1]=(pi){0,-1};
root=build(0,dfn+1);
int m=read();
while(m--){
char c[5];
scanf("%s",c);
if(c[0]=='Q'){
int x=read();
print(query(x));
printf("
");
}else if(c[0]=='C'){
int x=read(),y=read();
change(x,y);
}else{
int x=read(),y=read();
modify(x,x+n,y);
}
}
return 0;
}