• bzoj 3123: [Sdoi2013]森林(45分暴力)


    3123: [Sdoi2013]森林

    Time Limit: 20 Sec  Memory Limit: 512 MB
    Submit: 4184  Solved: 1235
    [Submit][Status][Discuss]

    Description

    Input

    第一行包含一个正整数testcase,表示当前测试数据的测试点编号。保证1≤testcase≤20。 
    第二行包含三个整数N,M,T,分别表示节点数、初始边数、操作数。第三行包含N个非负整数表示 N个节点上的权值。 
     接下来 M行,每行包含两个整数x和 y,表示初始的时候,点x和点y 之间有一条无向边, 接下来 T行,每行描述一个操作,格式为“Q x y k”或者“L x y ”,其含义见题目描述部分。

    Output

    对于每一个第一类操作,输出一个非负整数表示答案。 
     
     

    Sample Input

    1
    8 4 8
    1 1 2 2 3 3 4 4
    4 7
    1 8
    2 4
    2 1
    Q 8 7 3 Q 3 5 1
    Q 10 0 0
    L 5 4
    L 3 2 L 0 7
    Q 9 2 5 Q 6 1 6

    Sample Output

    2
    2
    1
    4
    2

    HINT



    对于第一个操作 Q 8 7 3,此时 lastans=0,所以真实操作为Q 8^0 7^0 3^0,也即Q 8 7 3。点8到点7的路径上一共有5个点,其权值为4 1 1 2 4。这些权值中,第三小的为 2,输出 2,lastans变为2。对于第二个操作 Q 3 5 1 ,此时lastans=2,所以真实操作为Q 3^2 5^2 1^2 ,也即Q 1 7 3。点1到点7的路径上一共有4个点,其权值为 1 1 2 4 。这些权值中,第三小的为2,输出2,lastans变为 2。之后的操作类似。 

     

     
    /*
        3~6这几个点的暴力写起来真难受,把链转化成数组的过程频频出错,更恶心的是离散化……
        7~9用的树剖维护链的最小值,这就让人很舒服了,1.2两个点直接暴力就行
        感觉11~13貌似可以用lct维护动态加边,然后统计链的最小值,但是码力太差写不出来,可能要补补lct了
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 80010
    #define INF 1000000000
    using namespace std;
    int n,m,Q,val[maxn],lastans,num,head[maxn];
    struct node{int to,pre;}e[maxn*2];
    int qread(){
        int i=0,j=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')j=-1;ch=getchar();}
        while(ch<='9'&&ch>='0'){i=i*10+ch-'0';ch=getchar();}
        return i*j;
    }
    void Insert(int from,int to){
        e[++num].to=to;
        e[num].pre=head[from];
        head[from]=num;
    }
    //-----------------------------------------------------------
    int hash[maxn],a[maxn],cnt,du[maxn],b[maxn],pos[maxn];
    int lc[maxn*30],rc[maxn*30],sum[maxn*30],root[maxn*30],siz;
    bool vis[maxn];
    void build(int &now,int pre,int l,int r,int v){
        now=++siz;sum[now]=sum[pre]+1;
        if(l==r)return;
        int mid=(l+r)>>1;
        lc[now]=lc[pre];rc[now]=rc[pre];
        if(v<=mid)build(lc[now],lc[pre],l,mid,v);
        else build(rc[now],rc[pre],mid+1,r,v);
    }
    int query(int x,int y,int l,int r,int k){
        if(l==r)return l;
        int mid=(l+r)>>1;
        int tmp=sum[lc[y]]-sum[lc[x]];
        if(tmp>=k)return query(lc[x],lc[y],l,mid,k);
        else return query(rc[x],rc[y],mid+1,r,k-tmp);
    }
    void work1(){
        for(int i=1;i<=n;i++)hash[i]=a[i]=val[i];
        sort(a+1,a+n+1);
        cnt=unique(a+1,a+n+1)-a-1;
        for(int i=1;i<=n;i++)hash[i]=lower_bound(a+1,a+cnt+1,hash[i])-a;
        int s=0;
        for(int i=1;i<=n;i++)
            if(du[i]==1){s=i;break;}
        int now=s;
        b[1]=s;int po=1;vis[s]=1;
        while(1){
            for(int i=head[now];i;i=e[i].pre){
                int to=e[i].to;
                if(vis[to])continue;
                now=to;b[++po]=to;vis[to]=1;
                break; 
            }
            if(po==n)break;
        }
        for(int i=1;i<=n;i++){pos[b[i]]=i;}
        for(int i=1;i<=n;i++)
            build(root[i],root[i-1],1,cnt,hash[b[i]]);
        char ch[5];
        int l,r,k;
        for(int i=1;i<=Q;i++){
            scanf("%s%d%d%d",ch,&l,&r,&k);
            l=l^lastans;r=r^lastans;k=k^lastans;
            if(pos[l]>pos[r])swap(l,r);
            int w=query(root[pos[l]-1],root[pos[r]],1,cnt,k);
            printf("%d
    ",a[w]);
            lastans=a[w];
        }
    }
    //-----------------------------------------------------------
    int dep[maxn],sz[maxn],son[maxn],fa[maxn],top[maxn],dfn[maxn],mn[maxn*4];
    int id;
    void dfs1(int x,int father){
        fa[x]=father;
        dep[x]=dep[father]+1;
        sz[x]=1;
        for(int i=head[x];i;i=e[i].pre){
            int to=e[i].to;
            if(to==father)continue;
            dfs1(to,x);
            sz[x]+=sz[to];
            if(sz[son[x]]<sz[to])son[x]=to;
        }
    }
    void dfs2(int x,int father){
        top[x]=father;
        dfn[x]=++id;a[id]=x;
        if(son[x])dfs2(son[x],father);
        for(int i=head[x];i;i=e[i].pre){
            int to=e[i].to;
            if(to==fa[x]||to==son[x])continue;
            dfs2(to,to);
        }
    }
    void build(int k,int l,int r){
        if(l==r){mn[k]=val[a[l]];return;}
        int mid=(l+r)>>1;
        build(k<<1,l,mid);build(k<<1|1,mid+1,r);
        mn[k]=min(mn[k<<1],mn[k<<1|1]);
    }
    int query_case789(int k,int l,int r,int opl,int opr){
        if(l>=opl&&r<=opr)return mn[k];
        int mid=(l+r)>>1;
        int res=INF;
        if(opl<=mid)res=min(res,query_case789(k<<1,l,mid,opl,opr));
        if(opr>mid)res=min(res,query_case789(k<<1|1,mid+1,r,opl,opr));
        return res;
    }
    int query_mn(int x,int y){
        int res=INF;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            res=min(res,query_case789(1,1,n,dfn[top[x]],dfn[x]));
            x=fa[top[x]];
        }
        if(dep[x]>dep[y])swap(x,y);
        res=min(res,query_case789(1,1,n,dfn[x],dfn[y]));
        return res;
    }
    void work2(){
        dfs1(1,0);dfs2(1,1);
        build(1,1,n);
        char ch[5];
        int l,r,k;
        for(int i=1;i<=Q;i++){
            scanf("%s%d%d%d",ch,&l,&r,&k);
            l^=lastans;r^=lastans;k^=lastans;
            lastans=query_mn(l,r);
            printf("%d
    ",lastans);
        }
    }
    //-----------------------------------------------------------
    void work3(){
        char ch[5];
        int x,y,k;
        while(Q--){
            scanf("%s",ch);
            if(ch[0]=='L'){
                scanf("%d%d",&x,&y);
                x^=lastans;y^=lastans;
                Insert(x,y);Insert(y,x);
            }
            else {
                scanf("%d%d%d",&x,&y,&k);
                x^=lastans;y^=lastans;k^=lastans;
                dfs1(x,0);
                int cnt=0;
                while(y!=x){
                    a[++cnt]=val[y];
                    y=fa[y];
                }
                a[++cnt]=val[x];
                sort(a+1,a+cnt+1);
                printf("%d
    ",a[k]);
                lastans=a[k];
            }
        }
    }
    //-----------------------------------------------------------
    int main(){
        freopen("forest.in","r",stdin);freopen("forest.out","w",stdout);
        int Case;Case=qread();
        n=qread();m=qread();Q=qread();
        for(int i=1;i<=n;i++)scanf("%d",&val[i]);
        int x,y;
        for(int i=1;i<=m;i++){
            x=qread();y=qread();
            du[x]++;du[y]++;
            Insert(x,y);Insert(y,x);
        }
        if(Case<=6&&Case>=3){work1();return 0;}
        if(Case<=9&&Case>=7){work2();return 0;}
        work3();return 0;
    }
  • 相关阅读:
    自定义的事件管理器
    解决修改表结构,添加外键时出现“约束冲突”的错误
    jQuery学习(二) 自定义扩展函数
    iBt(001-004)原文与试译
    老婆怀孕了!(5+6)
    Mac_如何打开系统文件library
    Mac_如何通过命令行装包到ios手机
    MAC干净卸载pycharm
    selenium自动化_如何启动safari浏览器
    selenium自动化_click方法点击无效
  • 原文地址:https://www.cnblogs.com/thmyl/p/8682032.html
Copyright © 2020-2023  润新知