zoukankan      html  css  js  c++  java
  • 洛谷试炼场 4-17 树链剖分


    layout: post
    title: 洛谷试炼场 4-17 树链剖分
    author: "luowentaoaa"
    catalog: true
    mathjax: true
    tags:
    - 树链剖分
    - 数据结构
    - 洛谷


    [ZJOI2008]树的统计 (入门题,链最大值,链和)

    思路

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    int n,q,a[maxn];
    vector<int>G[maxn];
    int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];
    int id[maxn],pre[maxn],cnt=0;
    void dfs1(int u,int f,int deep){
        size[u]=1;
        fa[u]=f;son[u]=0;dep[u]=deep;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==f)continue;
            dfs1(v,u,deep+1);
            size[u]+=size[v];
            if(size[v]>size[son[u]])son[u]=v;
        }
    }
    void dfs2(int u,int root){
        id[u]=++cnt;top[u]=root;pre[cnt]=u;
        if(son[u])dfs2(son[u],root);
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==fa[u]||v==son[u])continue;
            dfs2(v,v);
        }
    }
    int sumv[maxn<<2],maxv[maxn<<2];
    inline void pushup(int o){
        sumv[o]=sumv[o<<1]+sumv[o<<1|1];
        maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
    }
    void build(int o,int l,int r){
        int mid=(l+r)/2;
        if(l==r){
            sumv[o]=maxv[o]=a[pre[l]];return;
        }
        build(o<<1,l,mid);build(o<<1|1,mid+1,r);
        pushup(o);
    }
    void update(int o,int l,int r,int q,int v){
        int mid=(l+r)/2;
        if(l==r){
            sumv[o]=maxv[o]=v;return;
        }
        if(q<=mid)update(o<<1,l,mid,q,v);
        else update(o<<1|1,mid+1,r,q,v);
        pushup(o);
    }
    int querysum(int o,int l,int r,int ql,int qr){
        int mid=(l+r)/2,ans=0;
        if(ql<=l&&r<=qr)return sumv[o];
        if(ql<=mid)ans+=querysum(o<<1,l,mid,ql,qr);
        if(qr>mid)ans+=querysum(o<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    int querymax(int o,int l,int r,int ql,int qr){
        int mid=(l+r)/2,ans=-inf;
        if(ql<=l&&r<=qr)return maxv[o];
        if(ql<=mid)ans=max(ans,querymax(o<<1,l,mid,ql,qr));
        if(qr>mid)ans=max(ans,querymax(o<<1|1,mid+1,r,ql,qr));
        return ans;
    }
    int qsum(int u,int v){
        int ans=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            ans+=querysum(1,1,n,id[top[u]],id[u]);
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])swap(u,v);
        ans+=querysum(1,1,n,id[v],id[u]);
        return ans;
    }
    int qmax(int u,int v){
        int ans=-inf;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            ans=max(ans,querymax(1,1,n,id[top[u]],id[u]));
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])swap(u,v);
        ans=max(ans,querymax(1,1,n,id[v],id[u]));
        return ans;
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin>>n;
        for(int i=1;i<n;i++){
            int u,v;
            cin>>u>>v;G[u].push_back(v);G[v].push_back(u);
        }
        for(int i=1;i<=n;i++)cin>>a[i];
        fa[1]=1;dfs1(1,0,1);dfs2(1,1);build(1,1,n);
        int q;
        cin>>q;
        while(q--){
            int x,y;char s[100];
            cin>>s>>x>>y;
            if(s[1]=='H')update(1,1,n,id[x],y);
            else if(s[1]=='M')cout<<qmax(x,y)<<endl;
            else if(s[1]=='S')cout<<qsum(x,y)<<endl;
        }
        return 0;
    }
    

    [P2486 SDOI2011]染色 (区间操作很难 未AC)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    int n,q,col[maxn];
    vector<int>G[maxn];
    int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];
    int id[maxn],pre[maxn],cnt=0;
    void dfs1(int u,int f,int deep){
        size[u]=1;
        fa[u]=f;son[u]=0;dep[u]=deep;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==f)continue;
            dfs1(v,u,deep+1);
            size[u]+=size[v];
            if(size[v]>size[son[u]])son[u]=v;
        }
    }
    void dfs2(int u,int root){
        id[u]=++cnt;top[u]=root;pre[cnt]=u;
        if(son[u])dfs2(son[u],root);
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==fa[u]||v==son[u])continue;
            dfs2(v,v);
        }
    }
    struct node{
        int l,r;
        int num,lazy,lc,rc;
    }my[maxn<<2];
    void push_up(int o){
        my[o].lc=my[o<<1].lc;my[o].rc=my[(o<<1)|1].rc;
        int ans=my[o<<1].num+my[(o<<1)|1].num;
        if(my[o<<1].rc==my[(o<<1)|1].lc)ans--;
        my[o].num=ans;
    }
    void push_down(int o){
        if(my[o].lazy){
            my[o<<1].lazy=my[(o<<1)|1].lazy=my[o].lazy;
            my[o<<1].num=my[(o<<1)|1].num=1;
            my[o<<1].lc=my[o<<1].rc=my[o].lc;
            my[(o<<1)|1].lc=my[(o<<1)|1].rc=my[o].lc;
            my[o<<1].lazy=0;
        }
    }
    void build(int o,int l,int r){
        int mid=(l+r)/2;
        my[o].l=l;my[o].r=r;my[o].num=0;my[o].lazy=0;
        if(l==r){
            my[o].num=1;
            my[o].lc=my[o].rc=col[pre[l]];
            return;
        }
        build(o<<1,l,mid);build((o<<1)|1,mid+1,r);
        push_up(o);
    }
    void update(int o,int l,int r,int x){
        if(my[o].l==l&&my[o].r==r){
            my[o].num=my[o].lazy=1;
            my[o].lc=my[o].rc=x;
            return;
        }
        push_down(o);
        int mid=(my[o].l+my[o].r)/2;
        if(r<=mid)update(o<<1,l,r,x);
        else if(l>mid)update((o<<1)|1,l,r,x);
        else{
            update(o<<1,l,mid,x);update((o<<1)|1,mid+1,r,x);
        }
        push_up(o);
    }
    void uptree(int u,int v,int c){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            update(1,id[top[u]],id[u],c);
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])swap(u,v);
        update(1,id[v],id[u],c);
    }
    int lc,rc;
    int query(int o,int l,int r,int L,int R){
        if(my[o].l==L)lc=my[o].lc;
        if(my[o].r==R)rc=my[o].rc;
        if(my[o].l==l&&my[o].r==r)return my[o].num;
        push_down(o);
        int mid=(my[o].l+my[o].r)/2;
        if(r<=mid)return query(o<<1,l,r,L,R);
        else if(l>mid)return query((o<<1)|1,l,r,L,R);
        else{
            int ans=query(o<<1,l,mid,L,R);
            ans+=query((o<<1)|1,mid+1,r,L,R);
            if(my[o<<1].rc==my[(o<<1)|1].lc)ans--;
            return ans;
        }
        push_up(o);
    }
    int qutree(int u,int v){
        int ans1=-1,ans2=-1,ans=0;
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v),swap(ans1,ans2);
            ans+=query(1,id[top[u]],id[u],id[top[u]],id[u]);
            if(rc==ans1)ans--;
            ans1=lc;u=fa[top[u]];
        }
        if(dep[u]<dep[v])swap(u,v),swap(ans1,ans2);
        ans+=query(1,id[v],id[u],id[v],id[u]);
        if(rc==ans1)ans--;
        if(lc==ans2)ans--;
        return ans;
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int m;
        cin>>n>>m;
        for(int i=1;i<=n;i++)cin>>col[i];
        for(int i=1;i<n;i++){
            int u,v;cin>>u>>v;
            G[u].push_back(v);G[v].push_back(u);
        }
        dfs1(1,1,1);dfs2(1,1);build(1,1,n);
        while(m--){
            char s[150];
            cin>>s;
            int x,y;
            if(s[0]=='C'){
                int c;cin>>x>>y>>c;
                uptree(x,y,c);
            }
            else{
                cin>>x>>y;
                cout<<qutree(x,y)<<endl;
            }
        }
        return 0;
    }
    

    [P2146 NOI2015]软件包管理器

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=1e6+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    int n,q,col[maxn];
    vector<int>G[maxn];
    int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn];
    int id[maxn],pre[maxn],cnt=0;
    void dfs1(int u,int f,int deep){
        size[u]=1;
        fa[u]=f;son[u]=0;dep[u]=deep;
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==f)continue;
            dfs1(v,u,deep+1);
            size[u]+=size[v];
            if(size[v]>size[son[u]])son[u]=v;
        }
    }
    void dfs2(int u,int root){
        id[u]=++cnt;top[u]=root;pre[cnt]=u;
        if(son[u])dfs2(son[u],root);
        for(int i=0;i<G[u].size();i++){
            int v=G[u][i];
            if(v==fa[u]||v==son[u])continue;
            dfs2(v,v);
        }
    }
    int sum[maxn<<2],lazy[maxn<<2];
    void push_up(int o){
        sum[o]=sum[o<<1]+sum[o<<1|1];
    }
    void push_down(int o,int l,int r){
        if(lazy[o]){
            int mid=(l+r)/2;
            if(lazy[o]==-1)sum[o<<1]=sum[o<<1|1]=0,lazy[o<<1]=lazy[o<<1|1]=-1;
            else sum[o<<1]=mid-l+1,sum[o<<1|1]=r-mid,lazy[o<<1]=lazy[o<<1|1]=1;
            lazy[o]=0;
        }
    }
    void uninstall(int o,int l,int r,int ql,int qr,int x){
        if(ql<=l&&r<=qr){
            if(!x)lazy[o]=-1,sum[o]=0;
            else lazy[o]=1,sum[o]=r-l+1;return;
        }
        int mid=(l+r)/2;push_down(o,l,r);
        if(mid>=ql)uninstall(o<<1,l,mid,ql,qr,x);
        if(mid<qr)uninstall(o<<1|1,mid+1,r,ql,qr,x);
        push_up(o);
    }
    void install(int v,int x,int y){
        while(top[x]!=top[y]){
            if(dep[top[x]]<dep[top[y]])swap(x,y);
            uninstall(1,1,n,id[top[x]],id[x],v);
            x=fa[top[x]];
        }
        if(dep[x]<dep[y])swap(x,y);
        uninstall(1,1,n,id[y],id[x],v);
    }
    
    int main()
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin>>n;
        for(int i=2;i<=n;i++){
            int u;
            cin>>u;u++;
            G[i].push_back(u);
            G[u].push_back(i);
        }
        dfs1(1,1,1);
        dfs2(1,1);
        int m;cin>>m;
        char op[150];
        while(m--){
            int x;
            cin>>op>>x;x++;int p=sum[1];
            if(op[0]=='i'){
                install(1,x,1);
                cout<<abs(p-sum[1])<<endl;
            }
            else{
                uninstall(1,1,n,id[x],id[x]+size[x]-1,0);
                cout<<abs(p-sum[1])<<endl;
            }
        }
        return 0;
    }
    /*
    7
    0 0 0 1 1 5
    5
    install 5
    install 6
    uninstall 1
    install 4
    uninstall 0
    */
    
    

    [P3258 JLOI2014]松鼠的新家 (区间加减)

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const ll mod=998244353;
    const int maxn=3e5+50;
    const ll inf=0x3f3f3f3f3f3f3f3fLL;
    vector<int>G[maxn];
    int id[maxn],dep[maxn],pre[maxn],fa[maxn],size[maxn],son[maxn],cnt,top[maxn];
    void dfs1(int now,int f,int deep){
        fa[now]=f;size[now]=1;son[now]=0;dep[now]=deep;
        for(auto i:G[now]){
            if(i==f)continue;
            dfs1(i,now,deep+1);
            size[now]+=size[i];
            if(size[i]>size[son[now]])son[now]=i;
        }
    }
    void dfs2(int now,int root){
        id[now]=++cnt;pre[cnt]=now;top[now]=root;
        if(son[now])dfs2(son[now],root);
        for(auto i:G[now]){
            if(i==fa[now]||i==son[now])continue;
            dfs2(i,i);
        }
    }
    int sum[maxn<<2],lazy[maxn<<2];
    void push_up(int o){
        sum[o]=sum[o<<1]+sum[o<<1|1];
    }
    void push_down(int o,int l,int r){
        if(lazy[o]){
            int mid=(l+r)/2;
            lazy[o<<1]+=lazy[o];
            lazy[o<<1|1]+=lazy[o];
            sum[o<<1]+=(mid-l+1)*lazy[o];
            sum[o<<1|1]+=(r-mid)*lazy[o];
            lazy[o]=0;
        }
    }
    void update(int o,int l,int r,int ql,int qr,int w){
        int mid=(l+r)/2;
        if(ql<=l&&r<=qr){
            lazy[o]+=w;
            sum[o]+=(r-l+1)*w;
            return;
        }
        push_down(o,l,r);
        if(ql<=mid)update(o<<1,l,mid,ql,qr,w);
        if(qr>mid)update(o<<1|1,mid+1,r,ql,qr,w);
        push_up(o);
    }
    void print(int o,int l,int r,int ql,int qr){
        cout<<"o=="<<o<<" l="<<l<<" r="<<r<<" ql="<<ql<<" qr="<<qr<<endl;
        cout<<"sum="<<sum[o]<<endl;
    }
    int query(int o,int l,int r,int ql,int qr){
        //print(o,l,r,ql,qr);
        if(l==r){
            return sum[o];
        }
        int mid=(l+r)/2;
        push_down(o,l,r);
        if(ql<=mid)return query(o<<1,l,mid,ql,qr);
        else return query(o<<1|1,mid+1,r,ql,qr);
    }
    void uptree(int u,int v,int w){
        while(top[u]!=top[v]){
            if(dep[top[u]]<dep[top[v]])swap(u,v);
            update(1,1,cnt,id[top[u]],id[u],w);
            u=fa[top[u]];
        }
        if(dep[u]<dep[v])swap(u,v);
        update(1,1,cnt,id[v],id[u],w);
    }
    int a[maxn];
    // 适用于正负整数
    template <class T>
    inline bool read(T &ret)
    {
        char c;
        int sgn;
        if (c = getchar(), c == EOF) return 0; //EOF
        while (c != '-' && (c < '0' || c > '9')) c = getchar();
        sgn = (c == '-') ? -1 : 1;
        ret = (c == '-') ? 0 : (c - '0');
        while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
        ret *= sgn;
        return 1;
    }
    inline void out(int x)
    {
        if (x > 9) out(x / 10);
        putchar(x % 10 + '0');
    }
    int main()
    {
       /* std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);*/
        int n;
        //cin>>n;
        read(n);
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<n;i++){
            int u,v;
           // cin>>u>>v;
            read(u);read(v);
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs1(1,1,1);dfs2(1,1);
        for(int i=1;i<n;i++){
            uptree(a[i],a[i+1],1);
            uptree(a[i+1],a[i+1],-1);
        }
        for(int i=1;i<=n;i++){
           // cout<<query(1,1,n,id[i],id[i])<<endl;
            out(query(1,1,n,id[i],id[i]));
            puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    RAID介绍,RAID5,10制作与损坏恢复
    ELK 安装过程
    centos 系统 yum安装软件报错
    linux系统磁盘分区
    python实现遍历两个文件夹,比对文件异常,生成比对报告功能
    win10新装系统,显卡风扇转动,链接正常开机,但设备管理器如果显示,无法更新驱动
    navicat premium 破解,无限试用方法
    安装vmware workstations 12 +ubuntu 遇到的一些问题
    win10 如何打开telnet,ftp等服务
    linux集群架构-keepalived高可用
  • 原文地址:https://www.cnblogs.com/luowentao/p/10358514.html
Copyright © 2011-2022 走看看