2018 Multi-University Training Contest 7-1009 & hdu6394:Tree(LCT)
題目大意:
這題基本上就是彈飛綿羊的樹上版,所以題意就不多講了。
可以參考另外一篇部落格:彈飛綿羊普通版
解題思路:
首先肯定可以用樹分塊來寫,思路就是跟線性的是一樣的。其次的話如果用LCT的話近似裸題,只是需要求一下對於點x,向上跳k次會跳到哪個點,用倍增求出來即可。然後我添加了一個n+1作為1結點的父親,跳出去的點預設跳到n+1,之後就和線性的一樣了,這次主要也是為了測試LCT的板子,發現我的板子其實不夠優秀啊,裸跑998ms,所以用了dls的快讀,500+ms過了。。。
Ac程式碼:
#include<bits/stdc++.h> #define T_T system("pause") using namespace std; typedef long long ll; const int maxn=1e5+10; const int mod=1e9+7; const int INF=1e9+7; vector<int> v[maxn]; int n,m,dp[maxn][20],dep[maxn],a[maxn]; namespace IO{ //快讀板子 #define BUF_SIZE 100000 #define OUT_SIZE 100000 #define ll long long //fread->read bool IOerror=0; inline char nc(){ static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if (p1==pend){ p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if (pend==p1){IOerror=1;return -1;} //{printf("IO error!\n");system("pause");for (;;);exit(0);} } return *p1++; } inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} inline void read(int &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(ll &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(double &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (ch=='.'){ double tmp=1; ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); } if (sign)x=-x; } inline void read(char *s){ char ch=nc(); for (;blank(ch);ch=nc()); if (IOerror)return; for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; *s=0; } inline void read(char &c){ for (c=nc();blank(c);c=nc()); if (IOerror){c=-1;return;} } //fwrite->write struct Ostream_fwrite{ char *buf,*p1,*pend; Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;} void out(char ch){ if (p1==pend){ fwrite(buf,1,BUF_SIZE,stdout);p1=buf; } *p1++=ch; } void print(int x){ static char s[15],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); } void println(int x){ static char s[15],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); out('\n'); } void print(ll x){ static char s[25],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); } void println(ll x){ static char s[25],*s1;s1=s; if (!x)*s1++='0';if (x<0)out('-'),x=-x; while(x)*s1++=x%10+'0',x/=10; while(s1--!=s)out(*s1); out('\n'); } void print(double x,int y){ static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000, 1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL, 100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL}; if (x<-1e-12)out('-'),x=-x;x*=mul[y]; ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1; ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2); if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);} } void println(double x,int y){print(x,y);out('\n');} void print(char *s){while (*s)out(*s++);} void println(char *s){while (*s)out(*s++);out('\n');} void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}} ~Ostream_fwrite(){flush();} }Ostream; inline void print(int x){Ostream.print(x);} inline void println(int x){Ostream.println(x);} inline void print(char x){Ostream.out(x);} inline void println(char x){Ostream.out(x);Ostream.out('\n');} inline void print(ll x){Ostream.print(x);} inline void println(ll x){Ostream.println(x);} inline void print(double x,int y){Ostream.print(x,y);} inline void println(double x,int y){Ostream.println(x,y);} inline void print(char *s){Ostream.print(s);} inline void println(char *s){Ostream.println(s);} inline void println(){Ostream.out('\n');} inline void flush(){Ostream.flush();} #undef ll #undef OUT_SIZE #undef BUF_SIZE }; struct LCT //LCT模板 { int father[maxn+5],son[maxn+5][2],si[maxn+5]; bool flip[maxn+5]; void init() { memset(father,0,sizeof father); memset(son,0,sizeof son); memset(si,0,sizeof si); memset(flip,0,sizeof flip); for(int i=1;i<=n+1;i++) si[i]=1; } void Pushup(int p) {si[p]=si[son[p][0]]+1+si[son[p][1]];} void Add_flip(int p) {swap(son[p][0],son[p][1]);flip[p]^=1;} void Pushdown(int p) { if (!flip[p]) return; if (son[p][0]) Add_flip(son[p][0]); if (son[p][1]) Add_flip(son[p][1]); flip[p]=false; } bool is_ro(int p) {return p!=son[father[p]][0]&&p!=son[father[p]][1];} void Rotate(int p) { int fa=father[p],d=p==son[fa][0]; if (!is_ro(fa)) son[father[fa]][fa==son[father[fa]][1]]=p; son[fa][d^1]=son[p][d];father[son[p][d]]=fa;son[p][d]=fa; Pushup(fa);Pushup(p);father[p]=father[fa];father[fa]=p; } int top,stk[maxn+5]; void Splay(int p) { stk[++top]=p; for (int i=p;!is_ro(i);i=father[i]) stk[++top]=father[i]; while (top) Pushdown(stk[top--]); while (!is_ro(p)) { int fa=father[p]; if (!is_ro(fa)) { int d1=fa==son[father[fa]][1],d2=p==son[fa][1]; if (d1==d2) Rotate(fa); else Rotate(p); } Rotate(p); } } void Access(int p) { int lst=0; while (p) { Splay(p);son[p][1]=lst;Pushup(p); lst=p;p=father[p]; } } void make_ro(int p) {Access(p);Splay(p);Add_flip(p);} void Link(int x,int y) {Access(y);make_ro(y);father[y]=x;} void Cut(int x,int y) { make_ro(y);Access(x);Splay(x); father[y]=son[x][0]=0;Pushup(x); } }tr; void dfs(int u,int fa) //倍增 { dp[u][0]=fa; for(int i=1;i<=19;i++) dp[u][i]=dp[dp[u][i-1]][i-1]; for(int i=0;i<v[u].size();i++) dfs(v[u][i],u); } int query(int x,int t) //查詢x結點向上跳t次的結點 { for(int i=17;i>=0;i--) { if((1<<i)<=t) { if(dp[x][i]) x=dp[x][i],t-=(1<<i); else { x=n+1; break; } } } return x; } int main() { int QAQ; IO::read(QAQ); while(QAQ--) { IO::read(n); tr.init(); for(int i=0;i<=n+1;i++) v[i].clear(); for(int i=2;i<=n;i++) { int x; IO::read(x); v[x].push_back(i); } v[n+1].push_back(1); dfs(n+1,0); for(int i=1;i<=n;i++) //正常的連邊 { IO::read(a[i]); a[i]=query(i,a[i]); tr.Link(a[i],i); } IO::read(m); while(m--) { int flag,x,y; IO::read(flag); if(flag==1) //查詢x到n+1結點的鏈上點的個數 { IO::read(x); tr.make_ro(n+1);tr.Access(x);tr.Splay(x); IO::println(tr.si[x]-1); } if(flag==2) { IO::read(x),IO::read(y); tr.Cut(x,a[x]),tr.Link(x,query(x,y)); a[x]=query(x,y); } } } }
相關推薦
2018 Multi-University Training Contest 7-1009 & hdu6394:Tree(LCT)
題目大意: 這題基本上就是彈飛綿羊的樹上版,所以題意就不多講了。 可以參考另外一篇部落格:彈飛綿羊普通版 解題思路: 首先肯定可以用樹分塊來寫,思路就是跟線性的是一樣的。其次的話如果用LCT的話近似裸題,只是需要求一下對於點x,向上跳k次會跳到哪個點,用倍增求
ACM多校聯賽7 2018 Multi-University Training Contest 7 1009 Tree
ive tdi ini 我們 gis which print tmp bool 【題意概述】 給一棵以1為根的樹,樹上的每個節點有一個ai值,代表它可以傳送到自己的ai倍祖先,如果不存在則傳送出這棵樹。現在詢問某個節點傳送出這棵樹需要多少步。 【題解】 其實是把“
HDU - 6386 Age of Moyu 2018 Multi-University Training Contest 7 (Dijkstra變型)
pri == continue 不同 def ear color using find 題意:N個點M條邊的無向圖,每條邊都有屬於自己的編號,如果一條路徑上的邊編號都相同,那麽花費僅為1;改變至不同編號的路徑,花費加1,無論這個編號之前是否走過。 分析:記錄每個點的最小花費
題解:2018 Multi-University Training Contest 7
#include<bits/stdc++.h> #define mul(a,b,c) (1LL*(a)*(b)%(c)) using namespace std; typedef int
2018 Multi-University Training Contest 7 1008 Traffic Network in Numazu【樹鏈剖分】
題意:NN個節點NN條邊的連通圖,有刪改操作和線上查詢兩點間的最短路。 分析:相當於是一顆樹上多了一條邊,那麼找到一條這樣的邊(滿足刪除之後餘下整體為樹)把它刪掉。對於兩點間的查詢,由於有修改,就採用樹鏈剖分跑線段樹的方法來解決就OK。最後在計算答案的時候
2018 Multi-University Training Contest 7 1001 Age of Moyu【SPFA】
題意:給你一張圖,每條邊有一個代號。你可以花費1的代價來收買當前代號來通過這條邊,如果相鄰的邊屬於同一個代號走第二條邊不需要花費額外代價(如果經過了其他代號的邊再經過已收買的邊需要重新花費1代價)。 分析:那麼其實相比於常規的最短路只多了一個pre的判斷,
2018 Multi-University Training Contest 7 6390 GuGuFishtion【莫比烏斯反演】
昨天一下午,今天一上午,我已經快被這個題噁心死了。 TLE,TLE永遠都是TLE。不得不說,我覺得卡我卡的沒什麼道理,非常的不爽! 卡內迴圈列舉變數型別我是真的不懂,發現知識盲區+1. 可是就
2018 Multi-University Training Contest 7 1010 Sequence【整數分塊+矩陣冪】
題意:在擴充套件斐波納挈的基礎上加了一個變數P/nP/n。求第nn項的取值。 分析:考慮將每一種P/nP/n進行矩陣快速冪,也就是進行了整數分塊處理。對於每一個整數塊可以使用矩陣快速冪,然後維護A,BA,B用作下一次的矩陣快速冪使用。 整數分塊: 通過
2018 Multi-University Training Contest 7 1011 Swordsman【貪心+輸入掛】
題意:一開始你有k種魔法能力,每種能力是vi。每個怪物有k種防禦力,如果你的每一種能力都大於其相應的ai,就可以幹掉他,並且所有的能力都可以獲得一個提升bi。 注意:題目要求使用輸入掛 分析: 對於怪物按照每一個能力排一個序,然後維護當前每一種能力能幹
【2018 Multi-University Training Contest 7】GuGuFishtion(莫比烏斯反演)
Problem Description題目連結 Today XianYu is too busy with his homework, but the boring GuGu is still disturbing him!!!!!! At the brea
2018 Multi-University Training Contest 7 Sequence【矩陣快速冪+分塊】
Sequence Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 466 Accep
2018 Multi-University Training Contest 1
線段樹 tinc substr 線段 bst value 我們 ring lar 1001 Maximum Multiple 顯然,\(x\),\(y\),\(z\)三個數越接近越優秀 那麽當我們根據\(1=\frac{1}{3}+\frac{1}{3}+\frac{1}{
【2018 Multi-University Training Contest 2 1007】Naive Operations
min out ans ack ive txt 題解 syn class 【鏈接】 我是鏈接,點我呀:) 【題意】 給你兩個數組a,b; b數組是1..n的一個排列。 現在給你兩種操作: add l,r將a[l..r]都加上1 query l,r 詢問$∑^r_l
2018 Multi-University Training Contest 2
ring 交換 gif swap ans space deb add 數組 Game 題意: Alice和Bob先後手玩遊戲,每次可以從一個集合中拿出一個數(初始為1~n),拿出之後,這個數的所有因數都會從這個集合中消失,誰沒有數可拿時,就輸了。問Alice是否能贏?
HDU - 6315 Naive Operations (線段樹+思維) 2018 Multi-University Training Contest 2
延遲 給定 要求 lse define 位置 efi operation date 題意:數量為N的序列a和b,a初始全為0,b為給定的1-N的排列。有兩種操作:1.將a序列區間[L,R]中的數全部+1;2.查詢區間[L,R]中的 ∑?ai/bi?(向下取整) 分析:對於一
hdu 6319 Problem A. Ascending Rating (2018 Multi-University Training Contest 3 A)
while ble con -- test ++ nbsp ini for 鏈接: http://acm.hdu.edu.cn/showproblem.php?pid=6319 思路: 單調隊列倒著維護,隊列裏面剩下的值的數量就是這一段區間的count值,如樣例
2018 Multi-University Training Contest 4
names The else preview miss end res sent title Problem D. Nothing is Impossible Time Limit: 2000/1000 MS (Java/Others) Memory Limi
2018 Multi-University Training Contest 3 - HDU Contest
sub str define oid ini truct while enc -h 題解: solution Code: A. Ascending Rating #include<cstdio> const int N=10000010;
HDU 6356 Glad You Came 2018 Multi-University Training Contest 5 (線段樹)
build bsp clu const 區間更新 hup unsigned pda int 題目中沒有明說會爆int和longlong 的精度,但是在RNG函數中不用unsigned int 會報精度,導致隊友debug了很久... 根據每次生成的l,r,v對區間更新m次,
杭電2018多校第四場(2018 Multi-University Training Contest 4) 1004.Problem D. Nothing is Impossible (HDU6335) -思維題
假設 spa 。。 lan 多校 () class span tdi 6335.Problem D. Nothing is Impossible 題意:給你n道題目,m個人,每題有x個正確選項,y個錯誤選項,問你做對題數量最多的人做對了多少道題目。 如果一道題有