CF276E Little Girl and Problem on Trees 题解
Posted l_x_y
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF276E Little Girl and Problem on Trees 题解相关的知识,希望对你有一定的参考价值。
CF276E Little Girl and Problem on Trees 题解
题意
略。
分析
首先处理出所有链,对于修改操作,可以分两种情况讨论。设当前节点为 \\(u\\) ,距离为 \\(d\\) ,位于第 \\(num\\) 条链,在根以下第 \\(depth\\) 层。
第一种情况,若 \\(depth \\geq d\\) ,此时操作与其它链无关。可以给每条链建一个线段树,每次给区间 \\([depth-d,depth+d]\\) 的节点都加上 \\(x\\) 。
第二种情况,若 \\(depth < d\\) ,此时所有在根以下 \\([1,d-depth]\\) 层的节点都需要加上 \\(x\\) ,由于每次都是对整层的节点进行操作,因此再建一棵线段树,维护每一层加上的权值。除此之外,自己链上的符合要求的节点也需要加,就按照第一种情况的做法就行,需要注意刨掉在之前加过的几层里的节点。
对于查询操作,输出它所在层加的权值加上在本链中加的权值,需要注意特判一下大根。
开线段树时需要使用 vector ,不然 \\(1e5 \\times 1e5\\) 肯定会 MLE。
代码
#include <bits/stdc++.h>
#define int long long
#define mem(a,b) memset(a,b,sizeof(b))
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> Pair;
const int inf=2139062143;
const int MAXN=1e5+7;
inline void qread()template<class T1,class ...T2>
inline void qread(T1 &a,T2&... b)
register T1 x=0;register bool f=false;char ch=getchar();
while(ch<\'0\') f|=(ch==\'-\'),ch=getchar();
while(ch>=\'0\') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
x=(f?-x:x);a=x;qread(b...);
inline int qmax(const int &x,const int &y)return x>y?x:y;
inline int qmin(const int &x,const int &y)return x<y?x:y;
int n,q,cnt,dep[MAXN],mp[MAXN],sz[MAXN];
vector<int>tree[MAXN];
vector<int>b[MAXN];
void dfs(int u,int fa,int x)
int tmp=x;
if(fa==1) tmp=++cnt;
if(fa!=-1) b[tmp].push_back(u);
for(auto v:tree[u])
if(fa==v) continue;
if(fa==1||fa==-1) dfs(v,u,tmp);
else dfs(v,u,x);
struct Seg_Tree
vector<ll>Tree,tag;
inline ll ls(ll p)return p<<1;
inline ll rs(ll p)return p<<1|1;
inline void push_up(ll p)Tree[p]=Tree[ls(p)]+Tree[rs(p)];
inline void f(ll p,ll l,ll r,ll k)
tag[p]+=k;
Tree[p]+=(r-l+1)*k;
void push_down(ll p,ll l,ll r)
ll mid=(l+r)>>1;
f(ls(p),l,mid,tag[p]);
f(rs(p),mid+1,r,tag[p]);
tag[p]=0;
void update(ll p,ll l,ll r,ll L,ll R,ll k)
if(L<=l&&r<=R)
Tree[p]+=(r-l+1)*k,tag[p]+=k;
else
ll mid=(l+r)>>1;
push_down(p,l,r);
if(L<=mid) update(ls(p),l,mid,L,R,k);
if(R>mid) update(rs(p),mid+1,r,L,R,k);
push_up(p);
ll query(ll p,ll l,ll r,ll L,ll R)
if(L<=l&&r<=R) return Tree[p];
else
ll mid=(l+r)>>1,res=0;
push_down(p,l,r);
if(L<=mid) res+=query(ls(p),l,mid,L,R);
if(R>mid) res+=query(rs(p),mid+1,r,L,R);
return res;
t1,t[MAXN];
signed main()
qread(n,q);int i,j,mx=0,cnt1=0; // cnt1记录的是大根加的权值
for(i=0;i<n-1;i++)
int u,v;qread(u,v);
tree[u].push_back(v);
tree[v].push_back(u);
dfs(1,-1,0); // 处理出每条链
for(i=1;i<=cnt;i++)
b[i].insert(b[i].begin(),0);
for(j=1;j<b[i].size();j++)
mp[b[i][j]]=i; // 记录节点所在链的编号
dep[b[i][j]]=j; // 记录节点在根下的层数
mx=qmax(mx,b[i].size()-1); // 最大深度
sz[i]=b[i].size()-1; // 链的长度
for(i=1;i<=cnt;i++)
t[i].Tree.resize(mx<<2);
t[i].tag.resize(mx<<2);
t1.tag.resize(mx<<2);t1.Tree.resize(mx<<2);
while(q--)
int op,u,x,d;qread(op,u);
int depth=dep[u],num=mp[u];
if(op) // 查询
if(u==1) printf("%d\\n",cnt1);
else printf("%d\\n",t1.query(1,1,mx,depth,depth)+t[num].query(1,1,sz[num],depth,depth));
else
qread(x,d);
if(u==1) // 特别处理为大根的情况
cnt1+=x;
t1.update(1,1,mx,1,qmin(d,mx),x);
continue;
if(depth-d>=0) // 不牵扯其它链
t[num].update(1,1,sz[num],depth-d,qmin(depth+d,sz[num]),x);
if(depth==d) cnt1+=x;
else // 牵扯其它链
cnt1+=x;
if(d-depth+1<=sz[num]) t[num].update(1,1,sz[num],qmin(d-depth+1,sz[num]),qmin(depth+d,sz[num]),x);
t1.update(1,1,mx,1,qmin(d-depth,mx),x);
return 0;
以上是关于CF276E Little Girl and Problem on Trees 题解的主要内容,如果未能解决你的问题,请参考以下文章
Little Girl and Maximum Sum CodeForces - 276C
Codeforces Round #169 (Div. 2)C. Little Girl and Maximum Sum
C. Little Girl and Maximum Sum差分 / 贪心
D. Little Girl and Maximum XOR(贪心)