1. 程式人生 > >洛谷 P1505 [國家集訓隊]旅遊 解題報告

洛谷 P1505 [國家集訓隊]旅遊 解題報告

P1505 [國家集訓隊]旅遊

題目描述

\(\tt{Ray}\) 樂忠於旅遊,這次他來到了\(T\)城。\(T\)城是一個水上城市,一共有 \(N\) 個景點,有些景點之間會用一座橋連線。為了方便遊客到達每個景點但又為了節約成本,\(T\) 城的任意兩個景點之間有且只有一條路徑。換句話說, \(T\) 城中只有 \(N − 1\) 座橋。

\(\tt{Ray}\) 發現,有些橋上可以看到美麗的景色,讓人心情愉悅,但有些橋狹窄泥濘,令人煩躁。於是,他給每座橋定義一個愉悅度\(w\),也就是說,\(\tt{Ray}\) 經過這座橋會增加\(w\)的愉悅度,這或許是正的也可能是負的。有時,\(\tt{Ray}\)

看待同一座橋的心情也會發生改變。

現在,\(\tt{Ray}\) 想讓你幫他計算從\(u\)景點到\(v\)景點能獲得的總愉悅度。有時,他還想知道某段路上最美麗的橋所提供的最大愉悅度,或是某段路上最糟糕的一座橋提供的最低愉悅度。

輸入輸出格式

輸入格式:

輸入的第一行包含一個整數\(N\),表示\(T\)城中的景點個數。景點編號為 \(0\dots N − 1\)

接下來 \(N − 1\) 行,每行三個整數\(u\)\(v\)\(w\),表示有一條 \(u\)\(v\),使 \(\tt{Ray}\) 愉悅度增加 \(w\) 的橋。橋的編號為\(1\dots N − 1\)

\(|w| \le 1000\)。 輸入的第 \(N + 1\) 行包含一個整數\(M\),表示 \(\tt{Ray}\) 的運算元目。

接下來有 \(M\) 行,每行描述了一個操作,操作有如下五種形式:

  • C i w,表示\(\tt{Ray}\)對於經過第 \(i\) 座橋的愉悅度變成了 \(w\)

  • N u v,表示\(\tt{Ray}\) 對於經過景點 \(u\)\(v\) 的路徑上的每一座橋的愉悅度都變成原來的相反數。
  • SUM u v,表示詢問從景點 \(u\)\(v\) 所獲得的總愉悅度。
  • MAX u v,表示詢問從景點 \(u\)\(v\) 的路徑上的所有橋中某一座橋所提供的最大愉悅度。
  • MIN u v,表示詢問從景點 \(u\)\(v\) 的路徑上的所有橋中某一座橋所提供的最小愉悅度。

測試資料保證,任意時刻,\(\tt{Ray}\) 對於經過每一座橋的愉悅度的絕對值小於等於\(1000\)

輸出格式:

對於每一個詢問(操作\(S\)\(MAX\)\(MIN\)),輸出答案。


樹鏈剖分模板題,掛了好多個小時簡直自閉了。

奇怪的錯誤點:

  1. read()沒讀負數,最開始忘記生成負資料了一直拍不出來
  2. 若前向星的邊的編號除2得到原始編號,應該從2開始編號,隨機生成樹的時候沒打亂邊的順序沒拍出來。

Code:

#include <cstdio>
#include <cctype>
const int N=2e5+10;
int head[N],to[N<<1],edge[N<<1],Next[N<<1],cnt=1;
void add(int u,int v,int w)
{
    to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
    to[++cnt]=u,edge[cnt]=w,Next[cnt]=head[v],head[v]=cnt;
}
int read()
{
    int x=0,f=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') f=-f;c=getchar();}
    while(isdigit(c)) {x=x*10+c-'0';c=getchar();}
    return x*f;
}
int num[N],dtp[N],ha[N],top[N],f[N],dfn[N],dep[N],siz[N],ws[N],dfs_clock=-1;
void dfs1(int now)
{
    siz[now]=1;
    for(int i=head[now];i;i=Next[i])
    {
        int v=to[i];
        if(v!=f[now])
        {
            f[v]=now,dep[v]=dep[now]+1,num[i>>1]=v,dtp[v]=i;
            dfs1(v);
            siz[now]+=siz[v];
            if(siz[v]>siz[ws[now]]) ws[now]=v;
        }
    }
}
void dfs2(int now,int anc)
{
    dfn[now]=++dfs_clock;
    ha[dfs_clock]=now;
    top[now]=anc;
    if(ws[now]) dfs2(ws[now],anc);
    for(int i=head[now];i;i=Next[i])
        if(!dfn[to[i]]&&to[i]!=1)
            dfs2(to[i],to[i]);
}
int sum[N<<2],mx[N<<2],mi[N<<2],tag[N<<2],tot,tmp;
int n,m;char op[6];
#define ls id<<1
#define rs id<<1|1
int max(int x,int y){return x>y?x:y;}
int min(int x,int y){return x<y?x:y;}
void swap(int &x,int &y){tmp=x,x=y,y=tmp;}
void updata(int id)
{
    mx[id]=max(mx[ls],mx[rs]);
    mi[id]=min(mi[ls],mi[rs]);
    sum[id]=sum[ls]+sum[rs];
}
void build(int id,int l,int r)
{
    if(l==r)
    {
        sum[id]=mx[id]=mi[id]=edge[dtp[ha[l]]];
        return;
    }
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    updata(id);
}
void rev(int id)
{
    mx[id]=-mx[id],mi[id]=-mi[id];
    swap(mx[id],mi[id]);
}
void pushdown(int id)
{
    if(tag[id])
    {
        sum[ls]=-sum[ls],sum[rs]=-sum[rs];
        rev(ls),rev(rs);
        tag[ls]^=1,tag[rs]^=1;
        tag[id]^=1;
    }
}
void change(int id,int l,int r,int p,int d)
{
    if(l==r)
    {
        mx[id]=mi[id]=sum[id]=d;
        return;
    }
    pushdown(id);
    int mid=l+r>>1;
    if(p<=mid) change(ls,l,mid,p,d);
    else change(rs,mid+1,r,p,d);
    updata(id);
}
void Reverse(int id,int L,int R,int l,int r)
{
    if(L==l&&R==r)
    {
        tag[id]^=1,sum[id]=-sum[id],rev(id);
        return;
    }
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) Reverse(ls,L,Mid,l,r);
    else if(l>Mid) Reverse(rs,Mid+1,R,l,r);
    else Reverse(ls,L,Mid,l,Mid),Reverse(rs,Mid+1,R,Mid+1,r);
    updata(id);
}
void modify(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(dep[top[x]]>=dep[top[y]])
        {
            Reverse(1,1,n,dfn[top[x]],dfn[x]);
            x=f[top[x]];
        }
        else
        {
            Reverse(1,1,n,dfn[top[y]],dfn[y]);
            y=f[top[y]];
        }
    }
    if(dep[x]<dep[y]) swap(x,y);
    if(x!=y) Reverse(1,1,n,dfn[y]+1,dfn[x]);
}
int querys(int id,int L,int R,int l,int r)
{
    if(l==L&&r==R) return sum[id];
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) return querys(ls,L,Mid,l,r);
    else if(l>Mid) return querys(rs,Mid+1,R,l,r);
    else return querys(ls,L,Mid,l,Mid)+querys(rs,Mid+1,R,Mid+1,r);
}
int querysum(int x,int y)
{
    int s=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]>=dep[top[y]])
        {
            s+=querys(1,1,n,dfn[top[x]],dfn[x]);
            x=f[top[x]];
        }
        else
        {
            s+=querys(1,1,n,dfn[top[y]],dfn[y]);
            y=f[top[y]];
        }
    }
    if(dep[x]<dep[y]) swap(x,y);
    if(x!=y) s+=querys(1,1,n,dfn[y]+1,dfn[x]);
    return s;
}
int querymi(int id,int L,int R,int l,int r)
{
    if(l==L&&r==R) return mi[id];
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) return querymi(ls,L,Mid,l,r);
    else if(l>Mid) return querymi(rs,Mid+1,R,l,r);
    else return min(querymi(ls,L,Mid,l,Mid),querymi(rs,Mid+1,R,Mid+1,r));
}
int querymin(int x,int y)
{
    int s=N;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]>=dep[top[y]])
        {
            s=min(s,querymi(1,1,n,dfn[top[x]],dfn[x]));
            x=f[top[x]];
        }
        else
        {
            s=min(s,querymi(1,1,n,dfn[top[y]],dfn[y]));
            y=f[top[y]];
        }
    }
    if(dep[x]<dep[y]) swap(x,y);
    if(x!=y) s=min(s,querymi(1,1,n,dfn[y]+1,dfn[x]));
    return s;
}
int querymx(int id,int L,int R,int l,int r)
{
    if(l==L&&r==R) return mx[id];
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) return querymx(ls,L,Mid,l,r);
    else if(l>Mid) return querymx(rs,Mid+1,R,l,r);
    else return max(querymx(ls,L,Mid,l,Mid),querymx(rs,Mid+1,R,Mid+1,r));
}
int querymax(int x,int y)
{
    int s=-N;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]>=dep[top[y]])
        {
            s=max(s,querymx(1,1,n,dfn[top[x]],dfn[x]));
            x=f[top[x]];
        }
        else
        {
            s=max(s,querymx(1,1,n,dfn[top[y]],dfn[y]));
            y=f[top[y]];
        }
    }
    if(dep[x]<dep[y]) swap(x,y);
    if(x!=y) s=max(s,querymx(1,1,n,dfn[y]+1,dfn[x]));
    return s;
}
#define rep(i,a,b) for(int i=a;i<=b;i++)
int main()
{
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    n=read();
    int u,v,w;rep(i,1,(n-1)) u=read()+1,v=read()+1,w=read(),add(u,v,w);
    dep[1]=1,dfs1(1),dfs2(1,1);
    m=read();
    build(1,1,--n);
    rep(i,1,m)
    {
        scanf("%s",op);
        u=read()+1,v=read()+1;
        if(op[0]=='C') change(1,1,n,dfn[num[u-1]],v-1);
        else if(op[0]=='N') modify(u,v);
        else if(op[0]=='S') printf("%d\n",querysum(u,v));
        else if(op[1]=='A') printf("%d\n",querymax(u,v));
        else printf("%d\n",querymin(u,v));
    }
    return 0;
}

2018.11.5