zoukankan      html  css  js  c++  java
  • 「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!

  • 相关阅读:
    取得窗口大小和窗口位置兼容所有浏览器的js代码
    一个简单易用的导出Excel类
    如何快速启动chrome插件
    网页表单设计案例
    Ubuntu下的打包解包
    The source file is different from when the module was built. Would you like the debugger to use it anyway?
    FFisher分布
    kalman filter
    Group delay Matlab simulate
    24位位图格式解析
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/11347268.html
Copyright © 2011-2022 走看看