zoukankan      html  css  js  c++  java
  • bzoj 4448 [Scoi2015]情报传递 主席树

    比较套路的题目。

    可以发现难点在于某个点的权值动态修改 且我们要维护树上一条路径上的点权>x的个数。

    每个点都在动态修改 这意味着我们的只能暴力的去查每个点。

    考虑将所有可以动态修改的点变成静态的 这样查询好查 那么外部需要一个动态的标记 且这个标记适用于所有点。

    不难想到我们的循环标记i 即第i次操作 将这个东西变成每个点的标记 就可以刚好和题目中的动态修改吻合了。

    一个点此刻被打上动态修改标记 那么其权值的变化量为-i 因为外面有一个+i的标记了 这个标记时刻也在变和题目吻合。

    此时我们需要处理的只有树上某个点权值会变树上某条路径上>x的点的个数。

    只能考虑主席树了(发现这个问题还不是很好解决

    dfs序上建立主席树 利用对LCA的容斥即可解决问题。

    由于存在单点修改 外面套一个树状数组即可。码量过大 不妨考虑离线。

    考虑一个没有被修改过的点 其实不需要赋值相当于没有即可。

    考虑我们询问的形式为 当前时间 x+now>c c-now-x now-c>i 也就是查询now-c之前被修改过的点。

    对于一个询问 now-c来说我们考虑之后被修改过的点至少为now+1 而由于c>0 所以now-c<now+1.

    所以后面的修改对前面的没有任何的影响所以可以直接 树上建立主席树来离线查询。

    数据范围 是简化程序的基础。

    //#include<bitsstdc++.h>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<cctype>
    #include<cstdlib>
    #include<queue>
    #include<deque>
    #include<stack>
    #include<vector>
    #include<algorithm>
    #include<utility>
    #include<bitset>
    #include<set>
    #include<map>
    #define ll long long
    #define db double
    #define INF 1000000000
    #define ldb long double
    #define pb push_back
    #define get(x) x=read()
    #define gt(x) scanf("%d",&x)
    #define put(x) printf("%d
    ",x)
    #define putl(x) printf("%lld
    ",x)
    #define gc(a) scanf("%s",a+1)
    #define rep(p,n,i) for(RE int i=p;i<=n;++i)
    #define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
    #define fep(n,p,i) for(RE int i=n;i>=p;--i)
    #define pii pair<int,int> 
    #define F first
    #define S second
    #define mk make_pair
    #define RE register
    #define gf(x) scanf("%lf",&x)
    #define pf(x) ((x)*(x))
    #define ull unsigned long long
    #define P 1000000000000000ll
    #define l(p) t[p].l
    #define r(p) t[p].r
    #define sum(p) t[p].sum
    #define ls l(p),l,mid
    #define rs r(p),mid+1,r
    using namespace std;
    char buf[1<<15],*fs,*ft;
    inline char getc()
    {
        return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
    }
    inline int read()
    {
        RE int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    const int MAXN=200010;
    int n,len,id,m,cnt;
    int a[MAXN],root[MAXN];
    int f[MAXN][20],Log[MAXN],d[MAXN];
    int lin[MAXN],ver[MAXN],nex[MAXN];
    struct wy{int l,r;int sum;}t[MAXN*30],w[MAXN];
    inline void add(int x,int y){ver[++len]=y;nex[len]=lin[x];lin[x]=len;}
    inline void insert(int &p,int l,int r,int las,int x)
    {
        p=++id;t[p]=t[las];
        if(l==r){++sum(p);return;}
        int mid=(l+r)>>1;
        if(x<=mid)insert(ls,l(las),x);
        else insert(rs,r(las),x);
        sum(p)=sum(l(p))+sum(r(p));
    }
    inline void dfs(int x,int fa)
    {
        d[x]=d[fa]+1;
        rep(1,Log[d[x]],i)f[x][i]=f[f[x][i-1]][i-1];
        if(a[x])insert(root[x],1,m,root[fa],a[x]);
        else root[x]=root[fa];
        go(x)dfs(tn,x);
    }
    inline int LCA(int x,int y)
    {
        if(d[x]<d[y])swap(x,y);
        fep(Log[d[x]],0,i)if(d[f[x][i]]>=d[y])x=f[x][i];
        if(x==y)return x;
        fep(Log[d[x]],0,i)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
        return f[x][0];
    }
    inline int ask(int p,int l,int r,int x)
    {
        if(x<=0)return 0;
        if(r<=x)return sum(p);
        int mid=(l+r)>>1;
        if(x<=mid)return ask(ls,x);
        return ask(ls,x)+ask(rs,x);
    }
    int main()
    {
        //freopen("1.in","r",stdin);
        get(n);int rt;Log[0]=-1;
        rep(1,n,i)
        {
            f[i][0]=read();
            if(!f[i][0])rt=i;
            else add(f[i][0],i);
            Log[i]=Log[i>>1]+1;
        }
        get(m);
        rep(1,m,i)
        {
            int op,l,r,x;
            get(op);get(l);
            if(op==1)get(r),get(x),w[++cnt]=(wy){l,r,i-x};
            else a[l]=i;
        }
        dfs(rt,0);
        rep(1,cnt,i)
        {
            int lca=LCA(w[i].l,w[i].r);
            int L=w[i].l,R=w[i].r;
            int ww=w[i].sum-1;
            //cout<<-ask(root[lca],1,m,ww)*2<<endl;
            //put(ask(root[L],1,m,ww));
            printf("%d %d
    ",d[L]+d[R]-2*d[lca]+1,ask(root[L],1,m,ww)+ask(root[R],1,m,ww)-ask(root[lca],1,m,ww)*2+(a[lca]<=ww&&a[lca]));
        }
        return 0;
    }
    
  • 相关阅读:
    Sql中CHARINDEX用法
    Ubuntu 18.04 配置ibus中文拼音输入法(超简单)
    win10使用教程(电脑windows系统基础使用教程快速入门手册图文详解)
    angularjs中$scope是什么意思
    angularjs中$scope是什么意思?
    005列表标签
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
    Evanyou Blog 彩带
  • 原文地址:https://www.cnblogs.com/chdy/p/12642937.html
Copyright © 2011-2022 走看看