zoukankan      html  css  js  c++  java
  • CF1076E Solution

    题目链接

    题解

    \(n,m\le 3\cdot 10^5\)可看出,此题需在\(logn\)的时间内进行区间修改与单点查询。而描述操作位置的只有距离(子树深度)一个变量,可以想到以深度为关键字建立线段树或树状数组。

    设点\(i\)深度为\(pos_i\),对于每个操作将深度区间\([pos_{v_i},pos_{v_i}+d_i]+x_i\)即可。可以发现,若每个节点在将相关操作区间修改完毕后立刻计算答案,便可保证节点的修改不会影响到其祖先。因此区间修改时可直接将\([1,pos_{v_i}+d_i]+x_i\),这样用树状数组维护更加便捷。立刻计算答案还有另一个原因,为使修改不会影响到同级节点及其子节点,在回溯时需取消每个节点的修改。

    AC代码

    #include<bits/stdc++.h>
    #define lowb(x) x&(-x)
    #define int long long
    using namespace std;
    const int N=3e5+10;
    struct node {int v,d,x;} q[N];//操作
    int fst[N],nxt[2*N],v[2*N],cnt;
    int t[N],ans[N],n;//t:树状数组
    vector<int> qwq[N];//qwq[i]:d=i的操作下标
    void add(int x,int y)
    {
    	v[++cnt]=y;
    	nxt[cnt]=fst[x]; fst[x]=cnt;
    }
    void modif(int x,int y)
    {
    	while(x) {t[x]+=y; x-=lowb(x);}
    }
    int query(int x)
    {
    	int ans=0;
    	while(x<=n) {ans+=t[x]; x+=lowb(x);}
    	return ans;
    }
    void dfs(int x,int fa,int pos)
    {
    	int siz=qwq[x].size();
    	for(int i=0;i<siz;i++) modif(min(pos+q[qwq[x][i]].d,n),q[qwq[x][i]].x);//修改操作
        //因为pos+d可能会大于n(最大深度),因此需要取min
    	ans[x]=query(pos);
    	for(int i=fst[x];i;i=nxt[i])
    		if(v[i]!=fa) dfs(v[i],x,pos+1);
    	for(int i=0;i<siz;i++) modif(min(pos+q[qwq[x][i]].d,n),-q[qwq[x][i]].x);//取消修改
    }
    signed main()
    {
    	int m,x,y;
    	scanf("%lld",&n);
    	for(int i=1;i<n;i++) 
    	{
    		scanf("%lld%lld",&x,&y);
    		add(x,y); add(y,x);
    	}
    	scanf("%lld",&m);
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%lld%lld%lld",&q[i].v,&q[i].d,&q[i].x);
    		qwq[q[i].v].push_back(i); 
    	}
    	dfs(1,0,1);
    	for(int i=1;i<=n;i++) printf("%lld ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    Python 学习笔记(九)Python元组和字典(二)
    Python 学习笔记(九)Python元组和字典(一)
    Java适配器模式
    Java原型模式
    Java建造者模式
    java工厂模式
    封装图片处理方法
    TP中的图片水印
    THINKphp中复杂的查询
    THINKphp中常见的Request请求类
  • 原文地址:https://www.cnblogs.com/violetholmes/p/14369699.html
Copyright © 2011-2022 走看看