1. 程式人生 > >2018 Multi-University Training Contest 7-1009 & hdu6394:Tree(LCT)

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個錯誤選項,問你做對題數量最多的人做對了多少道題目。 如果一道題有