题解:

一道优秀的题目

有几种做法:

1.维护后缀和

刚开始我想的是维护前缀和

然后用$sum[x]-sum[y]>=dep[x]-dep[y]$来做

但是这样子树赋值为0这个操作就很难进行了

因为你查找的是链上最小值,所以不改子树上面的节点是做不了的

那我们换一种方式,单点改,查询区间最大后缀和

这样子树染白的时候我们就可以在x处减去一个上面的最大后缀和,那么就对子树没有影响了

然后再把子树清空一下就可以

其实这个东西就是动态dp。。。

$$f(v)=max(f(x)-1,0)+v[v]$$

这个只用查询链

所以我们只需要维护$f[v]=MAX(f[top]必选时的最大值k1,任意情况最大值k2)$就可以了(v都是必选点)

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for(int i=h;i<=t;i++)
#define dep(i,t,h) for(int i=t;i>=h;i--)
#define ll long long
#define me(x) memset(x,0,sizeof(x))
#define mep(x,y) memcpy(x,y,sizeof(y))
#define mid ((h+t)>>1)
namespace IO{
char ss[<<],*A=ss,*B=ss;
IL char gc()
{
return A==B&&(B=(A=ss)+fread(ss,,<<,stdin),A==B)?EOF:*A++;
}
template<class T> void read(T &x)
{
rint f=,c; while (c=gc(),c<||c>) if (c=='-') f=-; x=(c^);
while (c=gc(),c>&&c<) x=(x<<)+(x<<)+(c^); x*=f;
}
char sr[<<],z[]; ll Z,C1=-;
template<class T>void wer(T x)
{
if (x<) sr[++C1]='-',x=-x;
while (z[++Z]=x%+,x/=);
while (sr[++C1]=z[Z],--Z);
}
IL void wer1()
{
sr[++C1]=' ';
}
IL void wer2()
{
sr[++C1]='\n';
}
template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}
template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}
template<class T>IL T MAX(T x,T y){return x>y?x:y;}
template<class T>IL T MIN(T x,T y){return x<y?x:y;}
};
using namespace IO;
const int N=2.1e5;
struct re{
int a,b;
}e[N*];
int head[N],l,n,m;
IL void arr(int x,int y)
{
e[++l].a=head[x];
e[l].b=y;
head[x]=l;
}
struct re2{
int a[];
re2() { a[]=a[]=; }
re2(int x,int y) {a[]=x; a[]=y;};
re2 operator *(const re2 &o) const
{
re2 c;
c.a[]=a[]+o.a[]; c.a[]=MAX(a[]+o.a[],o.a[]);
return c;
}
};
int fa[N],num[N],son[N],dfn[N],top[N],cnt;
void dfs(int x,int y)
{
num[x]=; fa[x]=y;
for (rint u=head[x];u;u=e[u].a)
{
int v=e[u].b;
if (v!=y)
{
dfs(v,x);
num[x]+=num[v];
if (num[son[x]]<num[v]) son[x]=v;
}
}
}
void dfs1(int x,int y,int z)
{
top[x]=y; dfn[x]=++cnt;
if (son[x]) dfs1(son[x],y,x);
for (rint u=head[x];u;u=e[u].a)
{
int v=e[u].b;
if (v!=z&&v!=son[x])
{
dfs1(v,v,x);
}
}
}
struct sgt{
re2 sum[N*];
bool lazy[N*];
#define updata(x) sum[x]=sum[x*2]*sum[x*2+1]
IL void down(int x,int h,int t)
{
if (lazy[x])
{
lazy[x*]=lazy[x*+]=; lazy[x]=;
sum[x*]=re2(-(mid-h+),-);
sum[x*+]=re2(-(t-mid),-);
}
}
void build(int x,int h,int t)
{
if (h==t) { sum[x]=re2(-,-); return;}
build(x*,h,mid); build(x*+,mid+,t);
updata(x);
}
void change(int x,int h,int t,int pos,int k)
{
if (h==t) { sum[x]=re2(k,k);return; }
down(x,h,t);
if (pos<=mid) change(x*,h,mid,pos,k);
else change(x*+,mid+,t,pos,k);
updata(x);
}
re2 query(int x,int h,int t,int h1,int t1)
{
if (h1<=h&&t<=t1) return sum[x];
down(x,h,t);
if (h1<=mid&&mid<t1) return query(x*,h,mid,h1,t1)*query(x*+,mid+,t,h1,t1);
else if (h1<=mid) return query(x*,h,mid,h1,t1);
else return query(x*+,mid+,t,h1,t1);
}
void push(int x,int h,int t,int h1,int t1)
{
if (h1<=h&&t<=t1) { lazy[x]=; sum[x]=re2(-(t-h+),-); return;}
down(x,h,t);
if (h1<=mid) push(x*,h,mid,h1,t1);
if (mid<t1) push(x*+,mid+,t,h1,t1);
updata(x);
}
}S;
IL int query(int x)
{
int ans=-;
re2 p1=re2(,-);
while (x)
{
re2 p=S.query(,,n,dfn[top[x]],dfn[x]);
p1=p*p1;
ans=max(ans,p1.a[]);
x=fa[top[x]];
}
return ans;
}
int main()
{
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
read(n); read(m);
rep(i,,n)
{
int x;
read(x);
arr(i,x); arr(x,i);
}
dfs(,); dfs1(,,);
S.build(,,n);
rep(i,,m)
{
int kk,x;
read(kk); read(x);
if (kk==)
{
S.change(,,n,dfn[x],S.query(,,n,dfn[x],dfn[x]).a[]+);
}
if (kk==)
{
S.push(,,n,dfn[x],dfn[x]+num[x]-);
int ans=query(x);
S.change(,,n,dfn[x],-ans-);
}
if (kk==)
{
if (query(x)>=) cout<<"black"<<endl;
else cout<<"white"<<endl;
}
}
return ;
}

2.操作分块

分块这个东西有的时候的确简单巧妙。。

但一般我也不会去想分块。。

这个是看了别人题解的。。

我们以每$\sqrt{n}$个元素分一组

对块内的操作,我们等待$\sqrt{n}$都做完了再把这$\sqrt{n}$个操作加入树中

对于当前的询问,我们只需要树内的$\sqrt{n}$个节点的信息就可以了

我们可以建立虚树维护

本来打算学树上分块的。。。但发现这东西并没有啥用

会线段树合并/dsu on tree/树上莫队 应该不会也没啥关系

像这种利用虚树的题目还是比较多的

codeforces 502 g The Tree的更多相关文章

  1. Codeforces Round #502 (in memory of Leopoldo Taravilse, Div. 1 + Div. 2) G. The Tree

    G. The Tree time limit per test 3 seconds memory limit per test 256 megabytes input standard input o ...

  2. Codeforces 461B Appleman and Tree(木dp)

    题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每一个节点的父亲节点,以及每一个点的颜色(0表示白色,1表示黑色),切断这棵树的k ...

  3. [codeforces 549]G. Happy Line

    [codeforces 549]G. Happy Line 试题描述 Do you like summer? Residents of Berland do. They especially love ...

  4. CodeForces 794 G.Replace All

    CodeForces 794 G.Replace All 解题思路 首先如果字符串 \(A, B\) 没有匹配,那么二元组 \((S, T)\) 合法的一个必要条件是存在正整数对 \((x,y)\), ...

  5. Codeforces 1129 E.Legendary Tree

    Codeforces 1129 E.Legendary Tree 解题思路: 这题好厉害,我来复读一下官方题解,顺便补充几句. 首先,可以通过询问 \(n-1​\) 次 \((S=\{1\},T=\{ ...

  6. Codeforces 280C Game on tree【概率DP】

    Codeforces 280C Game on tree LINK 题目大意:给你一棵树,1号节点是根,每次等概率选择没有被染黑的一个节点染黑其所有子树中的节点,问染黑所有节点的期望次数 #inclu ...

  7. Codeforces A. Game on Tree(期望dfs)

    题目描述: Game on Tree time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  8. Codeforces 1207 G. Indie Album

    Codeforces 1207 G. Indie Album 解题思路 离线下来用SAM或者AC自动机就是一个单点加子树求和,套个树状数组就好了,因为这个题广义SAM不能存在 \(len[u] = l ...

  9. Codeforces Round #781(C. Tree Infection)

    Codeforces Round #781 C. Tree Infection time limit per test 1 second memory limit per test 256 megab ...

随机推荐

  1. Quartus13.1全编译出现引脚错误(神级bug)

    BUG现象:分配完管脚后全编译出现如下错误. Error (171172):Detected confilicting assignments for the following nodes.Erro ...

  2. 4.6 并发编程/IO模型

    并发编程/IO模型 背景概念 IO模型概念 IO模型分类 阻塞IO  (blocking IO) 特点: 两个阶段(等待数据和拷贝数据两个阶段)都被block 设置 server.setsockopt ...

  3. CSS概念,引入,选择器

    概念 层叠样式表,定义如何显示HTML元素. 使用方式 行内样式 不推荐使用此方式 结构 和 样式的 杂糅会影响后期的维护 <p style="color: red"> ...

  4. [HNOI2016]矿区

    [HNOI2016]矿区 平面图转对偶图 方法: 1.分成正反两个单向边,每个边属于一个面 2.每个点按照极角序sort出边 3.枚举每一个边,这个边的nxt就是反边的前一个(这样找到的是面的边逆时针 ...

  5. pip install升级包

    只需要python -m pip install --user --upgrade pip==9.0.3 只需要加一个--user

  6. Centos 7 最小化kvm部署

    1.检查CPU是否支持虚拟化 sh-4.2# grep -E '(vmx|svm)' /proc/cpuinfo # 若是无任何显示,则表示CPU不支持kvm虚拟化 2.关闭selinux sh-4. ...

  7. java io系列17之 System.out.println("hello world")原理

    我们初学java的第一个程序是"hello world" public class HelloWorld { public static void main(String[] ar ...

  8. 前端开发常用 Linux 命令

    clear // 清理命令窗口(可简写为cls) exit // 关闭命令窗口 mkdir 文件夹名 // 新建文件夹 cd 文件夹名 // 进入文件夹 cd .. // 返回上一级文件夹目录 rm ...

  9. ubuntu 16.04 安装 Mask_RCNN 遇到的问题集锦

    源码网页(Mask R-CNN for object detection and instance segmentation on Keras and TensorFlow): https://git ...

  10. python Flask web框架

    目录: --> Flask --> 配置文件 --> 配置文件解析 --> 配置文件导入 --> 路由 --> 路由参数 --> 常用路由匹配 --> ...