bzoj4538:[Hnoi2016]网络

传送门

已经极其接近的想到过正确做法了,但是没想到标记永久化,所以复杂度炸了
树链剖分,对于线段树每个节点开个堆(一开始用multiset,结果MLE了,想不通为什么)
考虑对于一次请求\(u,v\),只有当它的路径上的点坏掉的时候,它才会受到影响,所以除去这条路径上的所有点都应该有这个贡献
代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
void read(int &x) {
    char ch; bool ok;
    for(ok=0,ch=getchar(); !isdigit(ch); ch=getchar()) if(ch=='-') ok=1;
    for(x=0; isdigit(ch); x=x*10+ch-'0',ch=getchar()); if(ok) x=-x;
}
#define rg register
const int maxn=1e5+10;
int n,m,cnt,pre[maxn*2],nxt[maxn*2],h[maxn],size[maxn],dep[maxn];
int f[maxn],top[maxn],id[maxn],tmp,tot,x[maxn*2],y[maxn*2],z[maxn*2],ans;
struct o{int x,y;}w[maxn];
priority_queue<int>q[maxn*4],p[maxn*4];
int get_top(int x)
{
    while(!q[x].empty()&&!p[x].empty()&&q[x].top()==p[x].top())q[x].pop(),p[x].pop();
    return q[x].empty()?0:q[x].top();
}
struct oo{int l,r;}s[maxn*4];
void add(int x,int y)
{
    pre[++cnt]=y,nxt[cnt]=h[x],h[x]=cnt;
    pre[++cnt]=x,nxt[cnt]=h[y],h[y]=cnt;
}
void dfs(int x,int fa)
{
    size[x]=1;
    for(rg int i=h[x];i;i=nxt[i])
        if(pre[i]!=fa)
        {
            f[pre[i]]=x,dep[pre[i]]=dep[x]+1,
            dfs(pre[i],x),size[x]+=size[pre[i]];
        }
}
void dfs1(int x,int f)
{
    top[x]=f,id[x]=++tmp;int k=0;
    for(int i=h[x];i;i=nxt[i])
        if(dep[pre[i]]>dep[x]&&size[pre[i]]>=size[k])k=pre[i];
    if(!k)return ;dfs1(k,f);
    for(rg int i=h[x];i;i=nxt[i])
        if(dep[pre[i]]>dep[x]&&pre[i]!=k)dfs1(pre[i],pre[i]);
}
void build(int x,int l,int r)
{
    s[x].l=l,s[x].r=r;int mid=(l+r)>>1;
    if(l==r)return ;
    build(x<<1,l,mid),build(x<<1|1,mid+1,r);
}
bool cmp(o a,o b){return a.x<b.x;}
void change(int x,int l,int r,int v,int id)
{
    if(l<=s[x].l&&r>=s[x].r)
    {
        if(id)q[x].push(v);else p[x].push(v);
        return ;
    }
    int mid=(s[x].l+s[x].r)>>1;
    if(l<=mid)change(x<<1,l,r,v,id);
    if(r>mid)change(x<<1|1,l,r,v,id);
}
void modify(int x,int y,int val,int flag)
{
    tot=0;
    while(top[x]!=top[y])
    {
        if(dep[top[x]]<dep[top[y]])swap(x,y);
        w[++tot]=(o){id[top[x]],id[x]};
        x=f[top[x]];
    }
    if(id[x]>id[y])swap(x,y);
    w[++tot]=(o){id[x],id[y]};
    sort(w+1,w+tot+1,cmp);int las=1;
    for(rg int i=1;i<=tot;i++)
    {
        if(las<=w[i].x-1)change(1,las,w[i].x-1,val,flag);
        las=w[i].y+1;
    }
    if(las<=n)change(1,las,n,val,flag);
}
int get(int x,int t)
{
    if(s[x].l==s[x].r)return get_top(x);
    int mid=(s[x].l+s[x].r)>>1,ans=get_top(x);
    if(t<=mid)return max(get(x<<1,t),ans);
    else return max(get(x<<1|1,t),ans);
}
int main()
{
    read(n),read(m);
    for(rg int i=1,u,v;i<n;i++)read(u),read(v),add(u,v);
    dfs(1,0),dfs1(1,1),build(1,1,n);
    for(rg int i=1,opt,t;i<=m;i++)
    {
        read(opt);
        if(opt==0)
        {
            read(x[i]),read(y[i]),read(z[i]);
            modify(x[i],y[i],z[i],1);
        }
        if(opt==1)
        {
            read(t);
            modify(x[t],y[t],z[t],0);
        }
        if(opt==2)read(t),ans=get(1,id[t]),printf("%d\n",ans?ans:-1);
    }
}
posted @ 2019-04-01 18:45 蒟蒻--lichenxi 阅读(...) 评论(...) 编辑 收藏