NC20558. [HNOI2016]网络
描述
输入描述
第一行两个正整数n,m,分别描述服务器和事件个数。服务器编号是从1开始的,因此n个服务器的编号依次是1 ,2,3,…,n。
接下来n-1行,每行两个正整数u,v,描述一条树边。u和v是服务器的编号。接下来m行,按发生时刻依 次描述每一个事件;即第i行(i=1,2,3,…,m)描述时刻i发生的事件。
每行的第一个数type描述事件类型,共3种类型:
(1)若type=0,之后有三个正整数a,b,v,表示服务器a,b之间出现一条重要度为v的数据交互请求;
(2)若type=1,之后有一个正整数t,表示时刻t(也就是第t个发生的事件)出现的数据交互请求结束;
(3)若type=2 ,之后有一个正整数x,表示服务器x在这一时刻出现了故障。对于每个type为2的事件,就是一次询问,即询问“ 当服务器x发生故障时,未被影响的请求中重要度的最大值是多少?”注意可能有某个服务器自身与自身进行数据 交互的情况。2 ≤ n ≤ 10^5, 1 ≤ m ≤ 2×10^5,其他的所有输入值不超过 10^9
输出描述
对于每个type=2的事件,即服务器出现故障的事件,输出一行一个整数,描述未被影响的请求中重要度的最大 值。如果此时没有任何请求,或者所有请求均被影响,则输出-1。
示例1
输入:
13 23 1 2 1 3 2 4 2 5 3 6 3 7 4 8 4 9 6 10 6 11 7 12 7 13 2 1 0 8 13 3 0 9 12 5 2 9 2 8 2 2 0 10 12 1 2 2 1 3 2 7 2 1 0 9 5 6 2 4 2 5 1 7 0 9 12 4 0 10 5 7 2 1 2 4 2 12 1 2 2 5 2 3
输出:
-1 3 5 -1 1 -1 1 1 3 6 7 7 4 6
说明:
解释其中的部分询问;下面的解释中用(a,b;t,v)表示在t时刻出现的服务器a和b之间的重
要度为v的请求:
对于第一个询问(在时刻1),此时没有任何请求,输出-1。
对于第四个询问(在时刻6),此时有两条交互(8,13;2,3),(9,12;3,5),所有询问均经过2
号服务器,输出-1。
对于第五个询问(在时刻8),此时有三条交互(8,13;2,3),(9,12;3,5),(10,12;7,1),只有交互
(10,12;7,1)没有经过2号服务器,因此输出其重要度1。
对于最后一个询问(在时刻23),此时有三条交互(9,5;12,6),(9,12;16,4),(10,5;17,7)。当3
号服务器出现故障时,只有交互(9,5;12,6)没有经过3号服务器,因此输出6。
C++14(g++5.4) 解法, 执行用时: 869ms, 内存消耗: 30948K, 提交时间: 2019-10-29 22:07:50
// luogu-judger-enable-o2 //It is made by M_sea #include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #include <queue> #define re register using namespace std; inline int read() { int X=0,w=1; char c=getchar(); while (c<'0'||c>'9') { if (c=='-') w=-1; c=getchar(); } while (c>='0'&&c<='9') X=X*10+c-'0',c=getchar(); return X*w; } const int N=200000+10; int n,m; struct Edge { int v,nxt; } e[N<<1]; int head[N]; inline void addEdge(int u,int v) { static int cnt=0; e[++cnt]=(Edge){v,head[u]},head[u]=cnt; } struct Query { int op,ans,id,x; } q[N],lq[N],rq[N]; int a[N],b[N],v[N]; bool operator <(Query a,Query b) { return a.id<b.id; } int fa[N],sz[N],dep[N],hson[N],top[N]; int st[N],ed[N],dfs_clock=0; inline void dfs1(int u,int f) { fa[u]=f,sz[u]=1,dep[u]=dep[f]+1,st[u]=++dfs_clock; for (re int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if (v==f) continue; dfs1(v,u); sz[u]+=sz[v]; if (sz[v]>sz[hson[u]]) hson[u]=v; } ed[u]=dfs_clock; } inline void dfs2(int u,int anc) { top[u]=anc; if (hson[u]) dfs2(hson[u],anc); for (re int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if (v!=fa[u]&&v!=hson[u]) dfs2(v,v); } } inline int LCA(int u,int v) { int x=top[u],y=top[v]; while (x!=y) { if (dep[x]>dep[y]) u=fa[x],x=top[u]; else v=fa[y],y=top[v]; } return dep[u]<dep[v]?u:v; } int c[N],mx; #define lowbit(x) (x&-x) inline void add(int x,int y) { for (;x<=n;x+=lowbit(x)) c[x]+=y; } inline int sum(int x) { int ans=0; for (;x;x-=lowbit(x)) ans+=c[x]; return ans; } inline void modify(int u,int v,int w) { int t=LCA(u,v); add(st[u],w),add(st[v],w),add(st[t],-w); if (fa[t]) add(st[fa[t]],-w); } inline void solve(int lval,int rval,int L,int R) { if (L>R) return; if (lval==rval) { for (re int i=L;i<=R;++i) if (q[i].op==2) q[i].ans=lval; return; } int mid=(lval+rval)>>1,lt=0,rt=0,path=0; for (re int i=L;i<=R;++i) { if (q[i].op==2) { if (sum(ed[q[i].x])-sum(st[q[i].x]-1)==path) lq[++lt]=q[i]; else rq[++rt]=q[i]; } else { if (v[q[i].x]<=mid) lq[++lt]=q[i]; else { int v=q[i].op?-1:1; path+=v; modify(a[q[i].x],b[q[i].x],v); rq[++rt]=q[i]; } } } for (re int i=L;i<=R;++i) { if (q[i].op==2||v[q[i].x]<=mid) continue; int v=q[i].op?1:-1; modify(a[q[i].x],b[q[i].x],v); } for (re int i=1;i<=lt;++i) q[L+i-1]=lq[i]; for (re int i=1;i<=rt;++i) q[L+lt+i-1]=rq[i]; solve(lval,mid,L,L+lt-1); solve(mid+1,rval,L+lt,R); } int main() { n=read(),m=read(); for (re int i=1;i<n;++i) { int u=read(),v=read(); addEdge(u,v); addEdge(v,u); } dfs1(1,0); dfs2(1,1); for (re int i=1;i<=m;++i) { q[i].op=read(),q[i].id=i; if (!q[i].op) { a[i]=read(),b[i]=read(),v[i]=read(),q[i].x=i; mx=max(mx,v[i]); } else q[i].x=read(); } solve(-1,mx,1,m); sort(q+1,q+m+1); for (re int i=1;i<=m;++i) if (q[i].op==2) printf("%d\n",q[i].ans); return 0; }
C++11(clang++ 3.9) 解法, 执行用时: 1373ms, 内存消耗: 62632K, 提交时间: 2019-03-09 14:55:19
#include<iostream> #include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<queue> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define pa pair<int,int> #define N 100005 using namespace std; int n,m,cnt,tot; int head[N],d[N],fa[N],sz[N],son[N],pos[N],top[N]; pa p[N]; struct edge{int next,to;}e[N*2]; struct data{int a,b,v;}q[N*2]; struct Heap { priority_queue<int> a,b; void add(int x){a.push(x);} void del(int x){b.push(x);} int top() { while (!b.empty()&&a.top()==b.top()) a.pop(),b.pop(); return a.empty()?-1:a.top(); } }t[N*4]; inline int read() { int x=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void add_edge(int x,int y) { e[++cnt]=(edge){head[x],y};head[x]=cnt; e[++cnt]=(edge){head[y],x};head[y]=cnt; } void dfs1(int x,int f) { fa[x]=f;d[x]=d[f]+1;sz[x]=1;son[x]=0; for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (y!=f) { dfs1(y,x); sz[x]+=sz[y]; if (sz[y]>=sz[son[x]]) son[x]=y;//这里写>=可以过,写>就会MLE,别问我为什么 } } } void dfs2(int x,int chain) { pos[x]=++tot;top[x]=chain; if (son[x]) dfs2(son[x],chain); for(int i=head[x];i;i=e[i].next) { int y=e[i].to; if (y!=fa[x]&&y!=son[x]) dfs2(y,y); } } void change(int k,int l,int r,int L,int R,int val,int flg) { if (l==L&&r==R) { if (flg) t[k].add(val); else t[k].del(val); return; } int mid=(l+r)>>1; if (R<=mid) change(k<<1,l,mid,L,R,val,flg); else if (L>mid) change(k<<1|1,mid+1,r,L,R,val,flg); else change(k<<1,l,mid,L,mid,val,flg),change(k<<1|1,mid+1,r,mid+1,R,val,flg); } void solve(int x,int y,int val,int flg) { int tot=0; while (top[x]!=top[y]) { if (d[top[x]]<d[top[y]]) swap(x,y); p[++tot]=make_pair(pos[top[x]],pos[x]); x=fa[top[x]]; } if (d[x]>d[y]) swap(x,y); p[++tot]=make_pair(pos[x],pos[y]); sort(p+1,p+tot+1); p[0]=make_pair(0,0); p[tot+1]=make_pair(n+1,n+1); F(i,0,tot) { int l=p[i].second+1,r=p[i+1].first-1; if (l<=r) change(1,1,n,l,r,val,flg); } } int query(int k,int l,int r,int x) { if (l==r) return t[k].top(); int mid=(l+r)>>1; if (x<=mid) return max(t[k].top(),query(k<<1,l,mid,x)); else return max(t[k].top(),query(k<<1|1,mid+1,r,x)); } int main() { n=read();m=read(); F(i,1,n-1){int x=read(),y=read();add_edge(x,y);} dfs1(1,0);dfs2(1,1); F(i,1,m) { int opt=read(),x; if (opt==0) { q[i].a=read();q[i].b=read();q[i].v=read(); solve(q[i].a,q[i].b,q[i].v,1); } else if (opt==1){x=read();solve(q[x].a,q[x].b,q[x].v,0);} else{x=read();printf("%d\n",query(1,1,n,pos[x]));} } return 0; }