zoukankan      html  css  js  c++  java
  • [CTSC2008]网络管理(整体二分+树剖+树状数组)

    一道经典的带修改树链第 (k) 大的问题。

    我只想出三个 (log) 的解法。。。

    整体二分+树剖+树状数组。

    那不是暴力随便踩的吗???

    不过跑得挺快的。

    (Code Below:)

    // luogu-judger-enable-o2
    #include <bits/stdc++.h>
    #define lowbit(x) ((x)&(-(x)))
    using namespace std;
    const int maxn=80000+10;
    const int lim=1e8;
    int n,m,a[maxn],c[maxn],ans[maxn],cnt,num;
    int top[maxn],dep[maxn],siz[maxn],son[maxn],fa[maxn],id[maxn],tim;
    int head[maxn],to[maxn<<1],nxt[maxn<<1],tot;
    
    struct Query{
        int op,x,y,k,id;
    }q[maxn*3],q1[maxn*3],q2[maxn*3];
    
    inline int read(){
        register int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
        return (f==1)?x:-x;
    }
    
    inline void update(int x,int y){
        for(;x<=n;x+=lowbit(x)) c[x]+=y;
    }
    
    inline int sum(int x){
        int ans=0;
        for(;x;x-=lowbit(x)) ans+=c[x];
        return ans;
    }
    
    inline void clear(int x){
        for(;x<=n;x+=lowbit(x)){
            if(c[x]) c[x]=0;
            else break;
        }
    }
    
    inline void addedge(int x,int y){
        to[++tot]=y;
        nxt[tot]=head[x];
        head[x]=tot;
    }
    
    void dfs1(int x,int f){
        siz[x]=1;fa[x]=f;
        dep[x]=dep[f]+1;
        int maxson=-1;
        for(int i=head[x],y;i;i=nxt[i]){
            y=to[i];
            if(y==f) continue;
            dfs1(y,x);siz[x]+=siz[y];
            if(siz[y]>maxson) maxson=siz[y],son[x]=y;
        }
    }
    
    void dfs2(int x,int topf){
        top[x]=topf;id[x]=++tim;
        if(son[x]) dfs2(son[x],topf);
        for(int i=head[x],y;i;i=nxt[i]){
            y=to[i];
            if(y==fa[x]||y==son[x]) continue;
            dfs2(y,y);
        }
    }
    
    inline int query(int x,int y){
        int ans=0;
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]]) swap(x,y);
            ans+=sum(id[x])-sum(id[top[x]]-1);
            x=fa[top[x]];
        }
        if(dep[x]>dep[y]) swap(x,y);
        ans+=sum(id[y])-sum(id[x]-1);                                                                                                                                                                                                                                                                                                                                      
        return ans;
    }
    
    void solve(int L,int R,int l,int r){
        if(L>R) return ;
        if(l==r){
            for(int i=L;i<=R;i++){
                if(q[i].op==1) update(q[i].x,q[i].k);
                else {
                    if(q[i].k<=query(q[i].x,q[i].y)) ans[q[i].id]=l;
                    else ans[q[i].id]=-1;
                }
            }
            for(int i=L;i<=R;i++)
                if(q[i].op==1) clear(q[i].x);
            return ;
        }
        int mid=(l+r)>>1,cnt1=0,cnt2=0,val;
        for(int i=L;i<=R;i++){
            if(q[i].op==1){
                if(q[i].y<=mid) q1[++cnt1]=q[i];
                else update(q[i].x,q[i].k),q2[++cnt2]=q[i];
            }
            else {
                val=query(q[i].x,q[i].y);
                if(q[i].k>val) q[i].k-=val,q1[++cnt1]=q[i];
                else q2[++cnt2]=q[i];
            }
        }
        for(int i=L;i<=R;i++)
            if(q[i].op==1&&q[i].y>mid) clear(q[i].x);
        for(int i=1;i<=cnt1;i++) q[L+i-1]=q1[i];
        for(int i=1;i<=cnt2;i++) q[L+cnt1+i-1]=q2[i];
        solve(L,L+cnt1-1,l,mid);solve(L+cnt1,R,mid+1,r);
    }
    
    int main()
    {
        n=read(),m=read();
        int k,x,y;
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<n;i++){
            x=read(),y=read();
            addedge(x,y);addedge(y,x);
        }
        dfs1(1,0);dfs2(1,1);
        for(int i=1;i<=n;i++) q[++cnt]=(Query){1,id[i],a[i],1,0};
        while(m--){
            k=read(),x=read(),y=read();
            if(k==0){
                q[++cnt]=(Query){1,id[x],a[x],-1,0};
                q[++cnt]=(Query){1,id[x],y,1,0};
                a[x]=y;
            }
            else {
                q[++cnt]=(Query){2,x,y,k,++num};
            }
        }
        solve(1,cnt,0,lim);
        for(int i=1;i<=num;i++){
            if(ans[i]==-1) printf("invalid request!
    ");
            else printf("%d
    ",ans[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    java多线程调试
    nginx学习网站收录
    eclispe使用
    网站收集
    《TCP/IP详解卷1:协议》——第6章 ICMP:Internet控制报文协议(转载)
    深入理解计算机系统——第12章:用信号量同步线程
    《TCP/IP详解卷1:协议》——第5章 RARP:逆地址解析协议(转载)
    YYHS-Floor it(递推+矩阵乘法+快速幂)
    YYHS-数列
    (转)Tarjan应用
  • 原文地址:https://www.cnblogs.com/owencodeisking/p/10350766.html
Copyright © 2011-2022 走看看