【题目描述】
HA的MK 以前曾经同时与一些傻二哈交♂往♂,傻二哈们之间的关系成一棵树。
一开始每个傻二哈对他都有一个好感度。因为 MK 太神犇了,所以很多傻二哈给他出了一些题目,
他每 AC 一道 编号为WCG的傻二哈 出给他的题目会导致以 WCG为根的子树中除了 WCG 以外所有的傻二哈对他的好♂感♂度
下降。
操作 1: MK AC 了 WCG 出的题目导致以 WCG为根的子树中除了 WCG 以外所有的傻二哈对他的好♂感♂度下
降。
操作 2: MK 想要知道以 WCG 为根的子树中除了 WCG 以外还有几个对他好感度>0 的。
树根处的傻二哈编号为 0,它对 MK 的好♂感♂度♂可以看做是无限的
【输入格式】
第一行一个整数 N。
代表有 N+1 个傻二哈,编号分别是 0~N。
接下来 N 行每行两个整数,第一个整数表示编号为 i 的傻二哈的好♂感♂度♂ H,第二个整数表示第
i 个傻二哈在树上的父亲 Fi。(保证傻二哈 i 的父亲的编号小于 i)。
接下来一行一个整数 Q。
接下来 Q 行,每行一个操作。
第一类操作读入三个参数{1,Ai,Xi}表示 QY 使以 Ai 为根的子树中除了 Ai 以外所有的傻二哈
对他的好感度下降 Xi。
第二类操作读入两个参数{2,Ai}表示询问以 Ai 为根的子树中除了 Ai 以外有几个傻二哈对 MK
的好感度>0。
【输出格式】
对于每一个第二类操作,输出一行一个整数,表示所询问的答案。
【样例输入】
4 1 0 2 0 2 2 1 2 4 1 2 1 2 2 1 0 1 2 0
【样例输出】
1 1
【提示】
对于 30%的数据,满足 1<=N<=1000,1<=Q<=1000。
对于另外 20%的数据,保证数据纯随机生成。
对于 100%的数据,满足 1<=N<=10^5,1<=Q<=10^5,0<=Ai<=N,1<=Hi<=10^9,1<=Xi<=10^4,
0<=Fi<i。
【来源】
在此键入。
题解:记忆化线段树 删点的时候直接走到叶子并记录是否走过 走过了就不再走一遍 时间复杂度O(nlogn)代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int maxn=100000+10;
vector<int>A[maxn];
int B[maxn];
int dfn[maxn];
int size[maxn];
int v[maxn];
int ti=0;
int minn[maxn*4],num[maxn*4],tag[maxn*4];
int ql,qr;
inline void dfs(int x,int f){
dfn[x]=++ti;
v[ti]=B[x];
size[x]=1;
for(int i=0;i<A[x].size();i++){
int u=A[x][i];
if(u==f)
continue;
dfs(u,x);
size[x]+=size[u];
}
}
inline void pushdown(int o){
minn[o<<1]-=tag[o];
minn[o<<1|1]-=tag[o];
tag[o<<1]+=tag[o];
tag[o<<1|1]+=tag[o];
tag[o]=0;
}
inline void build(int o,int l,int r){
if(l==r){
num[o]=(v[l]>0);
minn[o]=v[l];
}
else {
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
minn[o]=min(minn[o<<1],minn[o<<1|1]);
num[o]=num[o<<1]+num[o<<1|1];
}
}
inline void add(int o,int l,int r,int x){
if(ql<=l&&r<=qr){
tag[o]+=x;
minn[o]-=x;
//pushdown(o);
if(minn[o]<=0){
if(l==r){
num[o]=0;
minn[o]=0x7fffffff;
tag[o]=0;
return ;
}
else {
pushdown(o);
int mid=(l+r)>>1;
add(o<<1,l,mid,0);
add(o<<1|1,mid+1,r,0);
minn[o]=min(minn[o<<1],minn[o<<1|1]);
num[o]=num[o<<1]+num[o<<1|1];
}
}
}
else if(l!=r){
pushdown(o);
int mid=(l+r)>>1;
if(ql<=mid)
add(o<<1,l,mid,x);
if(qr>mid)
add(o<<1|1,mid+1,r,x);
minn[o]=min(minn[o<<1],minn[o<<1|1]);
num[o]=num[o<<1]+num[o<<1|1];
}
}
inline int query(int o,int l,int r){
if(ql<=l&&r<=qr)
return num[o];
else if(l!=r){
int mid=(l+r)>>1;
int ans=0;
if(ql<=mid)
ans+=query(o<<1,l,mid);
if(qr>mid)
ans+=query(o<<1|1,mid+1,r);
return ans;
}
return 0;
}
int main(){
freopen("alone.in","r",stdin);
freopen("alone.out","w",stdout);
int n,m;
scanf("%d",&n);
n++;
int x;
for(int i=2;i<=n;i++){
scanf("%d %d",&B[i],&x);
A[x+1].push_back(i);
}
dfs(1,0);
build(1,1,n);
scanf("%d",&m);
int p;
for(int i=1;i<=m;i++){
scanf("%d",&p);
if(p==1){
int k;
scanf("%d %d",&x,&k);
x++;
ql=dfn[x]+1;
qr=dfn[x]+size[x]-1;
if(ql<=qr)
add(1,1,n,k);
}
else {
scanf("%d",&x);
x++;
int ans=0;
ql=dfn[x]+1;
qr=dfn[x]+size[x]-1;
if(ql<=qr)
ans=query(1,1,n);
printf("%d\n",ans);
}
}
return 0;
}