链接:https://ac.nowcoder.com/acm/contest/392/H
来源:牛客网
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
华华看书了解到,一起玩养成类的游戏有助于两人培养感情。所以他决定和月月一起种一棵树。因为华华现在也是信息学高手了,所以他们种的树是信息学意义下的。
华华和月月一起维护了一棵动态有根树,每个点有一个权值。刚开存档的时候,树上只有 0 号节点,权值为 0 。接下来有两种操作:
操作 1:输入格式
1 i
1 i,表示月月氪金使节点 i 长出了一个新的儿子节点,权值为0,编号为当前最大编号 +1(也可以理解为,当前是第几个操作 1,新节点的编号就是多少)。
操作 2:输入格式
2 i a
2 i a,表示华华上线做任务使节点 i 的子树中所有节点(即它和它的所有子孙节点)权值加 a 。
但是月月有时会检查华华有没有认真维护这棵树,会作出询问:
询问 3:输入格式
3 i
3 i,华华需要给出 i 节点此时的权值。
华华当然有认真种树了,不过还是希望能写个程序以备不时之需。
输入描述:
第一行一个正整数M,接下来M行,每行先输入一个正整数O表示操作类型,再输入一个非负整数i表示操作或询问的节点编号,如果O=2,再输入一个正整数a。
输出描述:
对于每个询问3,输出一个非负整数表示询问的答案。
示例1
输入
复制
9
1 0
2 0 1
3 0
3 1
1 0
1 1
2 0 2
3 1
3 3
输出
复制
1
1
3
2
备注
1≤M≤4×1e5,保证操作1的数量不超过1e5,保证操作2中的参数a满足1≤a≤999
先离线操作,建好树,然后用vis数组存储这棵树的dfs序,即i号点被搜到的时间为vis[i],因为同一颗子树内的vis总是连续的,
所以当一个点被修改时,其子树上的所有节点(vis[i],vis[i]+size[vis[i]]-1)这一段连续的区间就会被修改,
用线段树就可以处理了
这时候考虑一个问题
如果在这个点产生(1操作)之前就被2操作了怎么办?
其实这时候只需要把这个点置为0即可,这样就能抵消前面的影响。
刚开始写了一份java代码,发现还是会出现数组溢出的问题,然后改成c++就过了。也不知道怎么回事
两份代码都贴出来吧
希望看出错误的大佬可以指正,多谢。
c++版、
#include
using namespace std;
const int N=400000+10;
int head[N*4],nex[N*4],to[N*4],vis[N*4],siz[N*4],tree[N*4],lazy[N*4];
static int now=0,cnt=0,cnt1=0;
struct node{
int x,y,z;
}ss[N];
static void add(int x ,int y) {
now++;
to[now]=y;
nex[now]=head[x];
head[x]=now;
}
static void dfs(int x,int pre) {
vis[x]=++cnt1;
siz[x]=1;
for(int i=head[x];i!=0;i=nex[i]) {
int y=to[i];
if(vis[y]==0) {
dfs(y,x);
siz[x]+=siz[y];
}
}
}
void pushdown(int x) {
if(lazy[x]!=0) {
tree[x]+=lazy[x];
lazy[x<<1]+=lazy[x];
lazy[x<<1|1]+=lazy[x];
lazy[x]=0;
}
}
int fi(int i,int l,int r,int ch) {
pushdown(ch);
if(l==r) {
return tree[ch];
}
int m=(l+r)/2;
if(i<=m) {
return fi(i,l,m,ch<<1);
}
else return fi(i,m+1,r,ch<<1|1);
}
void change(int y,int l,int r,int ch) {
pushdown(ch);
if(l==r) {
tree[ch]=0;
return ;
}
int m=(l+r)/2;
if(y<=m)
change(y,l,m,ch<<1);
else
change(y,m+1,r,ch<<1|1);
}
void add1(int l, int r, int z,int L,int R,int ch) {
pushdown(ch);
if(L>=l&&R<=r) {
lazy[ch]+=z;
return;
}
int m=(L+R)/2;
if(l<=m) add1(l,r,z,L,m,ch<<1);
if(r>m) add1(l,r,z,m+1,R,ch<<1|1);
}
int main()
{
ios::sync_with_stdio(false);
int m;
cin>>m;
for(int i=0;i<m;i++){
int x,y,z;
cin>>x>>y;
if(x==1){
add(y,++cnt);
}
else if(x==2){
cin>>z;
ss[i].z=z;
}
ss[i].x=x;
ss[i].y=y;
}
dfs(0,-1);
int now1=1;
for(int i=0;i<m;i++) {
if(ss[i].x==1) {
change(vis[now1],1,cnt1,1);
now1++;
}
else if(ss[i].x==2) {
add1(vis[ss[i].y],vis[ss[i].y]+siz[ss[i].y]-1,ss[i].z,1,cnt1,1);
}
else if(ss[i].x==3) {
cout<<fi(vis[ss[i].y],1,cnt1,1)<<endl;
//System.out.println(fi(vis[ss[i].y],1,cnt1,1));
}
}
return 0;
}
java版
package myproject;
import java.io.BufferedReader;
import java.io.*;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
class S implements Comparable<S>
{
int x,y,z;
public S(int x,int y,int z) {
this.x=x;
this.y=y;
this.z=z;
}
public int compareTo(S o) {
return 0;
}
}
public class Main {
static int N=400000+10;
static S []ss =new S [N*4];
static int []head=new int [N*4];
static int []next =new int [N*4];
static int []to= new int [N*4];
static int []vis=new int [N*4];
static int []size=new int [N*4];
static int[]tree=new int [N*5];
static int []lazy=new int [N*5];
static int now=0,cnt=0,cnt1=0;
static void add(int x ,int y) {
now++;
to[now]=y;
next[now]=head[x];
head[x]=now;
}
static void dfs(int x,int pre) {
vis[x]=++cnt1;
size[x]=1;
for(int i=head[x];i!=0;i=next[i]) {
int y=to[i];
if(vis[y]==0) {
dfs(y,x);
size[x]+=size[y];
}
}
}
public static void main(String []args) throws IOException {
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String str=br.readLine();
int m=Integer.parseInt(str);
for(int i=0;i<m;i++) {
str=br.readLine();
String []s =str.split(" ");
int x=Integer.parseInt(s[0]);
int y=Integer.parseInt(s[1]);
int z=0;
if(x==1) {
add(y,++cnt);
}
if(x==2) {
z=Integer.parseInt(s[2]);
}
ss[i]=new S(x,y,z);
}
dfs(0,-1);
int now1=1;
for(int i=0;i<m;i++) {
if(ss[i].x==1) {
change(vis[now1],1,cnt1,1);
now1++;
}
else if(ss[i].x==2) {
add1(vis[ss[i].y],vis[ss[i].y]+size[ss[i].y]-1,ss[i].z,1,cnt1,1);
}
else if(ss[i].x==3) {
System.out.println(fi(vis[ss[i].y],1,cnt1,1));
}
}
}
static void pushdown(int x) {
if(lazy[x]!=0) {
tree[x]+=lazy[x];
lazy[x<<1]+=lazy[x];
lazy[x<<1|1]+=lazy[x];
lazy[x]=0;
}
}
private static int fi(int i,int l,int r,int ch) {
pushdown(ch);
if(l==r) {
return tree[ch];
}
int m=(l+r)/2;
if(i<=m) {
return fi(i,l,m,ch<<1);
}
else return fi(i,m+1,r,ch<<1|1);
}
private static void change(int y,int l,int r,int ch) {
pushdown(ch);
if(l==r) {
tree[ch]=0;
return ;
}
int m=(l+r)/2;
if(y<=m)
change(y,l,m,ch<<1);
else
change(y,m+1,r,ch<<1|1);
}
private static void add1(int l, int r, int z,int L,int R,int ch) {
pushdown(ch);
if(L>=l&&R<=r) {
lazy[ch]+=z;
return;
}
int m=(L+R)/2;
if(l<=m) add1(l,r,z,L,m,ch<<1);
if(r>m) add1(l,r,z,m+1,R,ch<<1|1);
}
}