身为一个强省(HN)+强校(CJ)的蒟蒻,天天gi烂。。我还能说什么呢。
于是在一堆大佬的鼓(you)励(pian)下,去做了一下HNOI2016的网络。。。
(其实是一位名叫网管的人给我们的LCA练习题(rand的))
至于正解,当年HNOI2016考场上没有人做出正解来,所以我肯定只会打暴力。
1.首先这是一堆对于链上的操作,所以我们很容易联想到树链剖分。
2.然后要求不被影响的最大值,即不经过他的最大值,这可以想到用堆来维护。
4.因为设计删除操作,我们就可以维护一个加入堆和一个删除堆,要top的时候如果两个堆的队首相同,就一直pop;
5.运用正难则反的思想,既然维护经过他的很难的话,那我们就对树链剖分后的线段树的每个节点维护不经过他的最大值;
6.那么如何维护不经过他的呢?首先在树链剖分跳LCA的时候,把跳的那些线段全部记录下来,因为跳的这些线段都是连续的,所以我们排一遍序,取这些夹在线段中间的区间进行修改即可。
7.而查询的时候就一路查下来并不断取MAX即可;
// MADE BY QT666
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define lson num<<1
#define rson num<<1|1
using namespace std;
typedef long long ll;
const int N=300050;
int gi()
{
int x=0,flag=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*flag;
}
int head[N],nxt[N*2],to[N*2],dfn[N],top[N],size[N],son[N],sum,dep[N],fa[N],n,m,tt;
struct ac
{
priority_queuea,d;
void push(int x) {a.push(x);}
void del(int x) {d.push(x);}
int top()
{
while(!d.empty()&&a.top()==d.top()) a.pop(),d.pop();
if(a.empty()) return -1;
return a.top();
}
}tree[N*5];
struct AC
{
int l,r;
}Data[N];
struct Ac
{
int x,y,z;
}q[N];
void dfs1(int x,int f)
{
dep[x]=dep[f]+1;size[x]=1;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y!=f)
{
dfs1(y,x);
fa[y]=x;
size[x]+=size[y];
if(size[y]>size[son[x]]) son[x]=y;
}
}
}
void dfs2(int x,int f)
{
dfn[x]=++sum,top[x]=f;
if(son[x]) dfs2(son[x],f);
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
}
}
void modify(int num,int l,int r,int L,int R,int type,int val)
{
if(L>R) return;
if(L<=l&&r<=R)
{
if(!type) tree[num].push(val);
else tree[num].del(val);
return;
}
int mid=(l+r)>>1;
if(L<=mid) modify(lson,l,mid,L,R,type,val);
if(R>mid) modify(rson,mid+1,r,L,R,type,val);
}
bool cmp(AC a,AC b)
{
return a.l>1;
if(x<=mid) return max(tree[num].top(),query(lson,l,mid,x));
else return max(tree[num].top(),query(rson,mid+1,r,x));
}
int main()
{
int x,y,z,type;
n=gi(),m=gi();
for(int i=1;i