zoukankan      html  css  js  c++  java
  • BZOJ2157: 旅游

    题解:裸树剖啊  线段树打打标记维护就好了啊  我为什么要写LCT啊  感觉石乐志了 我常数怎么这么大啊 我好菜了啊

    树剖版本:

    /**************************************************************
        Problem: 2157
        User: c20161007
        Language: C++
        Result: Accepted
        Time:716 ms
        Memory:21352 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    const int MAXN=2e5+10;
    const int inf=1e9+7;
    using namespace std;
    int n;
    int fa[MAXN],dep[MAXN],num[MAXN],son[MAXN];
    int key[MAXN];
    int pos[MAXN];
    vector<pair<int,pair<int,int> > >vec[MAXN];
    void dfs1(int v,int pre,int deep){
        fa[v]=pre;dep[v]=deep+1;num[v]=1;
        for(int i=0;i<vec[v].size();i++){
        int u=vec[v][i].first;
        if(u!=pre){
            key[u]=vec[v][i].second.first;
            pos[vec[v][i].second.second]=u;
            dfs1(u,v,deep+1);
            num[v]+=num[u];
            if(son[v]==-1||num[son[v]]<num[u])son[v]=u;
        }
        }
    }
    int p[MAXN],fp[MAXN],tp[MAXN];
    int cnt;
    void dfs2(int v,int td){
        p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
        if(son[v]!=-1)dfs2(son[v],td);
        for(int i=0;i<vec[v].size();i++){
        int u=vec[v][i].first;
        if(u!=fa[v]&&u!=son[v])dfs2(u,u);
        }
    }
    int sum[MAXN<<2],minn[MAXN<<2],maxx[MAXN<<2];
    bool flag[MAXN<<2];
    void up(int x){
        sum[x]=sum[x<<1]+sum[x<<1|1];
        minn[x]=min(minn[x<<1],minn[x<<1|1]);
        maxx[x]=max(maxx[x<<1],maxx[x<<1|1]);
    }
    void push(int x){
        if(flag[x]){
        flag[x<<1]^=1;flag[x<<1|1]^=1;
        sum[x<<1]*=-1;swap(minn[x<<1],maxx[x<<1]);minn[x<<1]*=-1;maxx[x<<1]*=-1;
        sum[x<<1|1]*=-1;swap(minn[x<<1|1],maxx[x<<1|1]);minn[x<<1|1]*=-1;maxx[x<<1|1]*=-1;
        flag[x]=0;
        }
    }
    void built(int rt,int l,int r){
        if(l==r){sum[rt]=minn[rt]=maxx[rt]=key[fp[l]];return ;}
        int mid=(l+r)>>1;
        built(rt<<1,l,mid);
        built(rt<<1|1,mid+1,r);
        up(rt);
    }
    void update(int rt,int l,int r,int t,int vul){
        if(l==r){sum[rt]=minn[rt]=maxx[rt]=vul;return ;}
        int mid=(l+r)>>1;
        push(rt);
        if(t<=mid)update(rt<<1,l,mid,t,vul);
        else update(rt<<1|1,mid+1,r,t,vul);
        up(rt);
    }
    void update1(int rt,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){
        flag[rt]^=1;
        sum[rt]*=-1;swap(minn[rt],maxx[rt]);
        minn[rt]*=-1;maxx[rt]*=-1;
        return ;
        }
        int mid=(l+r)>>1;
        push(rt);
        if(ql<=mid)update1(rt<<1,l,mid,ql,qr);
        if(qr>mid)update1(rt<<1|1,mid+1,r,ql,qr);
        up(rt);
    }
    pair<int,pair<int,int> >ans1;
    void querty(int rt,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){ans1.first+=sum[rt],ans1.second.first=min(ans1.second.first,minn[rt]),ans1.second.second=max(ans1.second.second,maxx[rt]);return ;}
        int mid=(l+r)>>1;
        push(rt);
        if(ql<=mid)querty(rt<<1,l,mid,ql,qr);
        if(qr>mid)querty(rt<<1|1,mid+1,r,ql,qr);
        up(rt);
    }
    void slove1(int u,int v){
        int uu=tp[u];int vv=tp[v];
        while(uu!=vv){
        if(dep[uu]<dep[vv])swap(u,v),swap(uu,vv);
        update1(1,1,n,p[uu],p[u]);
        u=fa[uu];uu=tp[u];
        }
        if(dep[u]>dep[v])swap(u,v);
        if(u!=v)update1(1,1,n,p[son[u]],p[v]);
    }
    int slove(int u,int v,int op){
        //cout<<u<<" "<<v<<endl;
        int uu=tp[u];int vv=tp[v];
     //   cout<<uu<<" "<<vv<<endl;
        ans1.first=0;ans1.second.first=inf;ans1.second.second=-1*inf;
        while(uu!=vv){
        if(dep[uu]<dep[vv])swap(u,v),swap(uu,vv);
        querty(1,1,n,p[uu],p[u]);
        u=fa[uu];uu=tp[u];
    //  cout<<vv<<" "<<uu<<endl;
        }
      //  cout<<ans1.first<<endl;
        if(dep[u]>dep[v])swap(u,v);
        if(u!=v)querty(1,1,n,p[son[u]],p[v]);
        if(op==1)return ans1.first;
        if(op==2)return ans1.second.first;
        return ans1.second.second;
    }
    int main(){
        scanf("%d",&n);int u,v,vul;
        for(int i=1;i<=n;i++)son[i]=-1;
        for(int i=1;i<n;i++){
        scanf("%d%d%d",&u,&v,&vul);u++;v++;
        vec[u].push_back(make_pair(v,make_pair(vul,i)));
        vec[v].push_back(make_pair(u,make_pair(vul,i)));
        }
        dfs1(1,0,0);dfs2(1,1);
      //  for(int i=1;i<=n;i++)cout<<p[i]<<" ";
      //  cout<<endl;
        built(1,1,n);
        int m;scanf("%d",&m);char str[5];
        for(int i=1;i<=m;i++){
        scanf("%s",str);
        scanf("%d%d",&u,&v);
        if(str[0]!='C')u++,v++;
        if(str[0]=='C')update(1,1,n,p[pos[u]],v);
        else if(str[0]=='N')slove1(u,v);
        else if(str[0]=='S')printf("%d
    ",slove(u,v,1));
        else if(str[1]=='I')printf("%d
    ",slove(u,v,2));
        else printf("%d
    ",slove(u,v,3));
        }
        return 0;
    }
    

     LCT版本:

    /**************************************************************
        Problem: 2157
        User: c20161007
        Language: C++
        Result: Accepted
        Time:544 ms
        Memory:4832 kb
    ****************************************************************/
     
    #include <bits/stdc++.h>
    const int MAXN=2e4+10;
    const int inf=1e9+7;
    #define mp make_pair
    #define pb push_back
    using namespace std;
    int ch[MAXN][2],res[MAXN],size[MAXN],flag[MAXN],maxx[MAXN],minn[MAXN],sum[MAXN],pre[MAXN],key[MAXN];
    int flag1[MAXN],f[MAXN][21],dep[MAXN];
    bool rt[MAXN];
    int st[MAXN],tp;
    typedef struct node{
        int v,vul,id;
    }node;
    vector<node>vec[MAXN];
    int vis[MAXN];
    int cnt;
    void Treavel(int x)
    {
        if(x)
        {
            Treavel(ch[x][0]);
            printf("结点%2d:左儿子 %2d 右儿子 %2d 父结点 %2d size=%2d key=%2d
    ",x,ch[x][0],ch[x][1],pre[x],size[x],key[x]);
            Treavel(ch[x][1]);
        }
    }
    void debug(int rp)
    {
        printf("root:%d
    ",rp);
        Treavel(rp);
    }
    inline void newnode(int x,int vul,int fa){
        ch[x][0]=ch[x][1]=0;
        flag1[x]=res[x]=flag[x]=0;size[x]=1;maxx[x]=minn[x]=key[x]=sum[x]=vul;
        pre[x]=fa;rt[x]=1;
        return ;
    }
    inline void reverse(int r){
        if(!r)return ;
        swap(ch[r][0],ch[r][1]);
        res[r]^=1;
    }
    inline void Add(int r,int vul){
        if(!r)return ;
        key[r]+=vul;maxx[r]+=vul;minn[r]+=vul;sum[r]+=size[r]*vul;
        flag[r]+=vul;
    }
    inline void Fan(int r){
        if(!r)return ;
        key[r]*=-1;sum[r]*=-1;swap(maxx[r],minn[r]);maxx[r]*=-1;minn[r]*=-1;
        flag1[r]^=1;
    }
    inline void push(int x){
        if(res[x]){
            reverse(ch[x][0]);
            reverse(ch[x][1]);
            res[x]^=1;
        }
        if(flag[x]){
            Add(ch[x][0],flag[x]);
            Add(ch[x][1],flag[x]);
            flag[x]=0;
        }
        if(flag1[x]){
            Fan(ch[x][0]);
            Fan(ch[x][1]);
            flag1[x]^=1;
        }
    }
    inline void up(int x){
        sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
        minn[x]=key[x];maxx[x]=key[x];
        if(minn[x]>minn[ch[x][0]])minn[x]=minn[ch[x][0]];
        if(minn[x]>minn[ch[x][1]])minn[x]=minn[ch[x][1]];
        if(maxx[x]<maxx[ch[x][0]])maxx[x]=maxx[ch[x][0]];
        if(maxx[x]<maxx[ch[x][1]])maxx[x]=maxx[ch[x][1]];    
        size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
    }
    inline bool pd1(int x){
         return ch[pre[x]][0]!=x&&ch[pre[x]][1]!=x;
    }
    inline void P(int x){
        int i;st[++tp]=x;
        for(i=x;!pd1(i);i=pre[i]) st[++tp]=pre[i];
        for(;tp;tp--) push(st[tp]);
    }
    inline void rotate(int x,int kind){
        int y=pre[x];
        pre[ch[x][kind]]=y;ch[y][!kind]=ch[x][kind];
        if(!rt[y])ch[pre[y]][ch[pre[y]][1]==y]=x;
        else rt[y]=0,rt[x]=1;
        pre[x]=pre[y];ch[x][kind]=y;pre[y]=x;
        up(y);up(x);
    }
    inline void splay(int x){
        P(x);
        while(!rt[x]){
            if(rt[pre[x]])rotate(x,ch[pre[x]][0]==x);
            else{
                int y=pre[x];int kind=ch[pre[y]][0]==y;
                if(ch[y][kind]==x)rotate(x,!kind),rotate(x,kind);
                else rotate(y,kind),rotate(x,kind);
            }
        }
        up(x);
    }
    inline void access(int x){
        int y=0;
        while(x){
            splay(x);
            if(ch[x][1])rt[ch[x][1]]=1,pre[ch[x][1]]=x,ch[x][1]=0;
            if(y)rt[y]=0;
            ch[x][1]=y;up(x);
            y=x;x=pre[x];
        }
    }
    inline void mroot(int x){
        access(x);splay(x);reverse(x);
    }
    void dfs(int v,int ff,int deep){
        f[v][0]=ff;dep[v]=deep+1;
        for(int i=0;i<vec[v].size();i++){
            if(vec[v][i].v!=ff){
                newnode(vec[v][i].v,vec[v][i].vul,v);
                vis[vec[v][i].id]=vec[v][i].v;
                dfs(vec[v][i].v,v,deep+1);
            }
        }
    }
    void dfs1(int v){
        for(int i=1;i<=20;i++)f[v][i]=f[f[v][i-1]][i-1];
        for(int i=0;i<vec[v].size();i++)if(vec[v][i].v!=f[v][0])dfs1(vec[v][i].v);
    }
    int Lca(int u,int v){
        if(dep[u]<dep[v])swap(u,v);
        int tmp=dep[u]-dep[v];
        for(int i=0;i<=20;i++)if((tmp&(1<<i)))u=f[u][i];
        if(u==v)return u;
        for(int i=20;i>=0;i--){
            if(f[u][i]!=f[v][i]){
                u=f[u][i];v=f[v][i];
            }
        }
        return f[u][0];
    }
    inline void update(int v,int vul){
        splay(v);key[v]=vul;up(v);
    }
    inline void update1(int u,int v){
        int lca=Lca(u,v);
        if(v!=lca){mroot(lca);access(v);splay(lca);Fan(ch[lca][1]);}
        if(u!=lca){mroot(lca);access(u);splay(lca);Fan(ch[lca][1]);}
        return ;
    }
    inline int querty(int u,int v){
        int lca=Lca(u,v);int t1=0;
        if(v!=lca){mroot(lca);access(v);splay(lca);t1+=sum[ch[lca][1]];}
        if(u!=lca){mroot(lca);access(u);splay(lca);t1+=sum[ch[lca][1]];}
        return t1;
    }
    inline int Max(int u,int v){
        int lca=Lca(u,v);int t1=-1*inf;
        //cout<<u<<" "v<<endl;
        if(v!=lca){mroot(lca);access(v);splay(lca);t1=max(t1,maxx[ch[lca][1]]);}
        if(u!=lca){mroot(lca);access(u);splay(lca);t1=max(t1,maxx[ch[lca][1]]);}
        return t1;
    }
    inline int Min(int u,int v){
        int lca=Lca(u,v);int t1=inf;
        if(v!=lca){mroot(lca);access(v);splay(lca);t1=min(t1,minn[ch[lca][1]]);}
        if(u!=lca){mroot(lca);access(u);splay(lca);t1=min(t1,minn[ch[lca][1]]);}
        return t1;
    }
    int main(){
        int n;scanf("%d",&n);int u,v,vul;
        sum[0]=0;maxx[0]=-inf;minn[0]=inf;
        for(int i=1;i<n;i++)scanf("%d%d%d",&u,&v,&vul),u++,v++,vec[u].pb((node){v,vul,i}),vec[v].pb((node){u,vul,i});
        dfs(1,0,0);dfs1(1);newnode(1,0,0);
        //cout<<pre[3]<<endl;
        int m;scanf("%d",&m);char str[15];
        for(int i=1;i<=m;i++){
            scanf("%s%d%d",str,&u,&v);
            if(str[0]=='C')update(vis[u],v);
            else if(str[0]=='N')u++,v++,update1(u,v);
            else if(str[0]=='S')u++,v++,printf("%d
    ",querty(u,v));
            else if(str[1]=='I')u++,v++,printf("%d
    ",Min(u,v));
            else if(str[1]=='A')u++,v++,printf("%d
    ",Max(u,v));
        }
        return 0;
    }
    

    2157: 旅游

    Time Limit: 10 Sec  Memory Limit: 259 MB
    Submit: 2471  Solved: 1017
    [Submit][Status][Discuss]

    Description

    Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。

    Input

    输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0...N − 1。接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。桥的编号为1...N − 1。|w| <= 1000。输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。接下来有M 行,每行描述了一个操作,操作有如下五种形式: C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。 N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。 SUM u v,表示询问从景点u 到v 所获得的总愉悦度。 MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。 MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。

    Output

    对于每一个询问(操作S、MAX 和MIN),输出答案。

    Sample Input

    3
    0 1 1
    1 2 2
    8
    SUM 0 2
    MAX 0 2
    N 0 1
    SUM 0 2
    MIN 0 2
    C 1 3
    SUM 0 2
    MAX 0 2

    Sample Output

    3
    2
    1
    -1
    5
    3

    HINT

    一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。

  • 相关阅读:
    Java设计模式之装饰模式
    学习Emacs系列教程(二):导航
    Android ProgressDialog 延时消失
    java设计模式装饰模式
    Java 字节流和字符流的相互转换
    emacs配置颜色主题
    Android ProgressDialog的使用
    个人管理 时间管理GTD流程图
    jQuery - 列表控件推荐
    WPF - 模板查看工具:Show Me The Template及如何查看第三方主题
  • 原文地址:https://www.cnblogs.com/wang9897/p/9458180.html
Copyright © 2011-2022 走看看