hdu5756
http://www.cnblogs.com/duoxiao/p/5777644.html 官方题解在这里
其实这道题不难,当初训练的时候不会做说明自己太弱
lazy标记不pushdown就是用lazy表示这个区间整体有哪些加减操作(大区间答案正确,子区间答案需要被所有祖先区间的lazy修正)
#include<bits/stdc++.h> using namespace std;
struct way{int po,next;} e[];
struct node{int laz,l,r,s,mx,mi;} tr[*];
struct qst{int l,r;} q[];
int l[],r[],a[],fa[],c[],d[],p[],h[];
int n,len,t,op,ans,qq,m; bool cmp(int a,int b)
{
if (l[a]==l[b]) return r[a]<r[b];
return l[a]<l[b];
} void add(int x,int y)
{
e[++len].po=y;
e[len].next=p[x];
p[x]=len;
} void dfs(int x)
{
l[x]=++t; c[t]=x;
for (int i=p[x]; i; i=e[i].next)
{
int y=e[i].po;
if (fa[x]!=y)
{
d[y]=d[x]+;
fa[y]=x;
dfs(y);
}
}
r[x]=t;
} void update(int i,int sz)
{
int l=tr[i].l, r=tr[i].r;
tr[i].s=tr[l].s+tr[r].s+tr[i].laz*sz;
tr[i].mx=max(tr[l].mx,tr[r].mx)+tr[i].laz;
tr[i].mi=min(tr[l].mi,tr[r].mi)+tr[i].laz;
} int build(int l,int r)
{
tr[++t].laz=;
if (l==r)
{
tr[t].mx=tr[t].mi=tr[t].s=d[c[l]];
return t;
}
int m=(l+r)>>,q=t;
tr[q].l=build(l,m);
tr[q].r=build(m+,r);
update(q,r-l+);
return q;
} void work(int i,int sz,int z)
{
tr[i].laz+=z;
tr[i].s+=z*sz;
tr[i].mx+=z;
tr[i].mi+=z;
} int add(int last,int l,int r,int x,int y)
{
tr[++t]=tr[last];
if (x<=l&&y>=r)
{
work(t,r-l+,-);
return t;
}
int m=(l+r)>>,q=t;
if (x<=m) tr[q].l=add(tr[last].l,l,m,x,y);
if (y>m) tr[q].r=add(tr[last].r,m+,r,x,y);
update(q,r-l+);
return q;
} void get(int x)
{
for (int i=p[x]; i; i=e[i].next)
{
int y=e[i].po;
if (fa[x]!=y)
{
h[y]=add(h[x],,n,l[y],r[y]);
work(h[y],n,);
get(y);
}
}
} void ask(int q,int l,int r,int x,int y,int laz)
{
if (op==&&laz+tr[q].mi>=ans) return;
if (op==&&laz+tr[q].mx<=ans) return;
if (x<=l&&y>=r)
{
if (op==) ans+=tr[q].s+(r-l+)*laz;
else if (op==) ans=min(ans,tr[q].mi+laz);
else if (op==) ans=max(ans,tr[q].mx+laz);
return;
}
int m=(l+r)>>;
if (x<=m) ask(tr[q].l,l,m,x,y,laz+tr[q].laz);
if (y>m) ask(tr[q].r,m+,r,x,y,laz+tr[q].laz);
} int main()
{
while (scanf("%d%d",&n,&qq)!=EOF)
{
len=; memset(p,,sizeof(p));
for (int i=; i<n; i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
t=; dfs(); t=;
h[]=build(,n); get();
ans=;
while (qq--)
{
int k,x; bool ff=;
scanf("%d%d%d",&k,&x,&op);
x=(x+ans)%n+;
for (int i=; i<=k; i++) scanf("%d",&a[i]);
if (op==) ans=;
else if (op==) ans=1e9;
else ans=-;
if (!k) {ff=; ask(h[x],,n,,n,);}
else {
sort(a+,a++k,cmp);
q[m=].l=l[a[]]; q[].r=r[a[]];
for (int i=; i<=k; i++)
if (l[a[i]]>q[m].r)
{
q[++m].l=l[a[i]];
q[m].r=r[a[i]];
}
else q[m].r=max(q[m].r,r[a[i]]);
q[m+].l=n+;
int st=, en=q[].l-;
for (int i=; i<=m; i++)
{
if (st<=en) {ff=; ask(h[x],,n,st,en,);}
st=q[i].r+,en=q[i+].l-;
}
if (st<=en) {ff=; ask(h[x],,n,st,en,);}
}
if (!ff) {puts("-1"); ans=;}
else printf("%d\n",ans);
}
}
}
hdu5756的更多相关文章
随机推荐
- 在CentOS6.5 下安装并使用Java开发opencv的配置(一)
1) 安装gcc以及cmake等等乱七八糟的软件 yum install gcc yum install python yum install cmake yum groupinstall " ...
- HDU 5650 异或
so easy Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Sub ...
- 蓝桥杯 最短路 spfa
问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环).请你计算从1号点到其他点的最短路(顶点从1到n编号). 输入格式 第一行两个整数n, m. 接下来的m行,每行有三个 ...
- 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)
P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...
- HDU1024 最大m子段和
Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others ...
- 动态切换input的 disables 属性
$("input[type='text']").each(function(){ if($(this).data('parent_id')){ var _each_this_par ...
- SpringBoot打war包并部署到tomcat下运行
一.修改pom.xml. 1.packaging改为war 2.build节点添加<finalName>你的项目名</finalName> 二.修改项目启动类,继承Spring ...
- 2017 济南综合班 Day 1
送分题(songfen) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK喜欢干一些有挑战的事,比如说求区间最大子段和.它知道这个题目有O(n)的做法.于 ...
- hdu4085 Peach Blossom Spring
Peach Blossom Spring http://acm.hdu.edu.cn/showproblem.php?pid=4085 Time Limit: 10000/5000 MS (Java/ ...
- leetcode 刷题日志 2018-3-28
树: 404. 左叶子之和 求所有左叶子结点之和 . 递归法 分析:递归法遍历结点,找左叶子结点 空指针判断 有左子节点?是叶子结点?是的话更新value的值 int sumOfLeftLeaves( ...