BZOJ 1146: [CTSC2008]网络管理Network

20 篇文章 0 订阅
11 篇文章 0 订阅

被数据结构题艹哭QAQ 果然我数据结构还是太弱了

如果你做过我blog上一篇的那道COT 那就好办很多了(没做的去做做?
虽说我并不是先做COT的 而是先做这题 (捂脸

这题在COT的基础上 考虑到修改一个点只会影响其子树内的点
那我们就可以想到用dfs序来搞 方便修改
所以用树状数组维护主席树 查询的时候就用上一题相同的套路 把所有要加减的主席树弄出来,然后一起在主席树上走就好
对了 为了主席树快一点 小一点 离散化一下是极好的

不懂的话 我觉得我的代码还是挺能看的 LCA用了O(n)那种….

然后我愉快地去抄了个网上最短的代码
诶 为啥我的代码 连这种题都没有100行

#include<bits/stdc++.h>
#define pa pair<int,int>
using namespace std;
const int N=8e4+2;
char B[1<<14],*S=B,*T=B;
#define gc (S==T&&(T=(S=B)+fread(B,1,1<<14,stdin),S==T)?-1:*S++)
inline int read(){
    int x=0,f=1; char ch=gc;
    while(ch<'0' || ch>'9'){if(ch=='-')f=-1; ch=gc;}
    while(ch>='0' && ch<='9'){x=(x<<1)+(x<<3)+ch-'0'; ch=gc;}
    return x*f;
}
struct ED{int y,nex;}e[N<<1]; int len,fir[N];
void ins(int x,int y){
    e[++len]=(ED){y,fir[x]},fir[x]=len;
}
int z[N<<1],fa[N],p[N],a[N],K[N],u[N],v[N],zl,tot,id,in[N],out[N];
int n,rt[N],lc[N*80],rc[N*80],s[N*80],L[N<<2],R[N<<2],sl,sr,c[N],lca[N];
bool vis[N];
vector<pa >q[N];
void upd(int &x,int l,int r,int k,int u){
    lc[++tot]=lc[x],rc[tot]=rc[x],s[tot]=s[x]+u,x=tot;
    if(l==r)return;
    int mid=l+r>>1;
    if(k<=mid)upd(lc[x],l,mid,k,u); else upd(rc[x],mid+1,r,k,u);
}
int query(int l,int r,int k){
    if(l==r)return l;
    int i,s1=0,s2=0,mid=l+r>>1;
    for(i=1;i<=sr;++i) s1+=s[rc[R[i]]],s2+=s[R[i]];
    for(i=1;i<=sl;++i) s1-=s[rc[L[i]]],s2-=s[L[i]];
    if(s2<k) return -1;
    if(k<=s1){
        for(i=1;i<=sl;++i)L[i]=rc[L[i]];
        for(i=1;i<=sr;++i)R[i]=rc[R[i]];
        return query(mid+1,r,k);
    }
    for(i=1;i<=sl;++i)L[i]=lc[L[i]];
    for(i=1;i<=sr;++i)R[i]=lc[R[i]];
    return query(l,mid,k-s1);
}
void get(int x,int k){
    if(k){R[++sr]=rt[x]; for(x=in[x];x;x-=x&-x)R[++sr]=c[x];}
    else {L[++sl]=rt[x]; for(x=in[x];x;x-=x&-x)L[++sl]=c[x];}
}
void change(int x,int k,int u){
    for(;x<=n;x+=x&-x) upd(c[x],1,zl,k,u);
}
int Find(int x){return x==p[x]?x:p[x]=Find(p[x]);}
void dfs(int x){
    p[x]=x,rt[x]=rt[fa[x]],upd(rt[x],1,zl,a[x],1);
    in[x]=++id;
    for(int k=fir[x];k;k=e[k].nex) if(fa[x]!=e[k].y){
        fa[e[k].y]=x; dfs(e[k].y); p[e[k].y]=x;
    } out[x]=id,vis[x]=1;
    int t=q[x].size();
    for(int i=0;i<t;++i) if(vis[q[x][i].first]) lca[q[x][i].second]=Find(q[x][i].first);
}
int main(){
    n=read(); int m=read(),x,y,i; zl=0;
    for(i=1;i<=n;++i) a[i]=z[++zl]=read();
    for(i=1;i<n;++i) x=read(),y=read(),ins(x,y),ins(y,x);
    for(i=1;i<=m;++i){
        K[i]=read(),u[i]=read(),v[i]=read();
        if(K[i])
            q[u[i]].push_back(pa(v[i],i)),
            q[v[i]].push_back(pa(u[i],i));
        else z[++zl]=v[i];
    }
    sort(z+1,z+1+zl); zl=unique(z+1,z+1+zl)-z-1;
    for(i=1;i<=n;++i) a[i]=lower_bound(z+1,z+1+zl,a[i])-z;
    dfs(n+1>>1);
    for(i=1;i<=m;++i)
        if(K[i]){
            sl=sr=0;
            get(u[i],1),get(v[i],1),get(lca[i],0),get(fa[lca[i]],0);
            int o=query(1,zl,K[i]);
            if(o<=0) puts("invalid request!");
            else printf("%d\n",z[o]);
        }
        else{
            x=u[i],y=lower_bound(z+1,z+1+zl,v[i])-z;
            change(in[x],a[x],-1),change(out[x]+1,a[x],1);
            change(in[x],y,1),change(out[x]+1,a[x]=y,-1);
        }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值