• 「2019-8-13提高模拟赛」树 (tree)


    传送门

    Description

    你有一个 (n)个点的树,第 (i)个点的父亲是(p_i)。每个点有一个权值 (t_i) 和一个颜色黑或者白。所有点一开始都是白色。

    你要进行 (m)次操作,每次给一个点换颜色(从白变成黑,从黑变成白),在每次操作结束时,问有多少个白点 (i) 的子树内黑点的个数大于 (t_i)

    Solution 

    相当于每次修改一条链的(t_i),让它们(+1/-1)

    树链剖分后分块处理

    复杂度(O(nsqrt n log n))

    Code 

    /*树剖+分块*/
    #include<bits/stdc++.h>
    #define ll long long
    #define dbg1(x) cerr<<#x<<"="<<(x)<<" "
    #define dbg2(x) cerr<<#x<<"="<<(x)<<"
    "
    #define dbg3(x) cerr<<#x<<"
    "
    using namespace std;
    #define reg register
    #define db double
    inline int read()
    {
    	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<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int MN=1e5+5,A=1e5;
    int fa[MN],n,m;
    vector<int> G[MN];
    int siz[MN],mx[MN];
    void dfs1(int x)
    {
    	reg int i;siz[x]=1;
    	for(i=G[x].size()-1;~i;--i)
    	dfs1(G[x][i]),siz[x]+=siz[G[x][i]],siz[G[x][i]]>siz[mx[x]]?mx[x]=G[x][i]:0;
    }
    int dind,id[MN],dfn[MN],top[MN];
    void dfs2(int x,int tp)
    {
    	id[dfn[x]=++dind]=x;top[x]=tp;if(mx[x])dfs2(mx[x],tp);reg int i;
    	for(i=G[x].size()-1;~i;--i)if(G[x][i]^mx[x])dfs2(G[x][i],G[x][i]);
    }
    int BL,cnt[500][MN<<1],t[MN],tag[500],T,bel[MN],ans;
    bool col[MN];
    void init()
    {
    	reg int i,l,r;
    	for(i=1;i<=n;++i) t[dfn[i]]=read();
    	BL=(int)ceil((db)sqrt(n));
    	for(T=1,l=1,r=BL;l<=n;++T,l=r+1,r=min(r+BL,n))
    		for(i=l;i<=r;++i)bel[i]=T,++cnt[T][t[i]+A];
    }
    void swi(int x)
    {
    	if(col[x]){++cnt[bel[x]][t[x]+A];if(t[x]<tag[bel[x]])++ans;}
    	else{--cnt[bel[x]][t[x]+A];if(t[x]<tag[bel[x]])--ans;}col[x]^=1;
    }
    void rough(int L,int R,int v)
    {
    	int x=bel[L],l=BL*x-BL+1,r=min(n,BL*x),i;
    	for(i=l;i<=r;++i)if(!col[i])--cnt[x][t[i]+A],ans-=(t[i]<tag[x]);
    	for(i=l;i<=r;++i)t[i]-=tag[x];tag[x]=0;
    	for(i=L;i<=R;++i)t[i]-=v;
    	for(i=l;i<=r;++i)if(!col[i])++cnt[x][t[i]+A],ans+=(t[i]<tag[x]);
    }
    void sol(int L,int R,int v)
    {
    	int xl=bel[L],xr=bel[R];
    	if(xl==xr)rough(L,R,v);
    	else
    	{
    		rough(L,xl*BL,v);rough(xr*BL-BL+1,R,v);
    		for(++xl;xl<xr;++xl)ans+=v*cnt[xl][tag[xl]-(v<0)+A],tag[xl]+=v;
    	}
    }
    void Upd(int x,int v){swi(dfn[x]);while(x)sol(dfn[top[x]],dfn[x],v),x=fa[top[x]];printf("%d ",ans);}
    int main()
    {
    #ifndef LOCAL
    	freopen("tree.in","r",stdin);
    	freopen("tree.out","w",stdout);
    #endif
    	n=read(),m=read();reg int i,q;
    	for(i=2;i<=n;++i)G[fa[i]=read()].push_back(i);
    	dfs1(1);dfs2(1,1);init();
    	while(m--) q=read(),Upd(abs(q),q/abs(q));
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    Gatling 条件判断
    Gatling脚本编写技巧篇(二)
    Gatling脚本编写技巧篇(一)
    性能测试-pidstat 问题定位分析
    REACT——无状态组件
    REACT——react-transition-group 实现动画
    REACT——生命周期函数
    REACT——ref的使用
    REACT——虚拟DOM
    REACT——Props、status与render
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/11347268.html
Copyright © 2020-2023  润新知