• [BZOJ4129]Haruna’s Breakfast


    description

    BZOJ
    题意:一棵n节点树,每个节点上有一个自然数ai。m次操作,每次修改一个节点上的数字,或者是询问路径u,v上最小的未出现的自然数是多少。

    data range

    [1le nle 5 imes 10^4,1le mle 5 imes 10^4,1le a_ile 10^9 ]

    solution

    重新学习莫队。

    树上莫队+带修莫队。
    首先要会树分块...

    然后把(u)(v)按照(dfn)排序(之前没有按照(dfn)排序比(zsy)的慢几百倍)
    此时的(u)(v)相当于区间的([l,r])

    计算答案时对权值分块统计
    有点码。

    Code

    #include<bits/stdc++.h>
    #include<algorithm>
    #include<iostream>
    #include<cstdlib>
    #include<iomanip>
    #include<cstring>
    #include<complex>
    #include<vector>
    #include<cstdio>
    #include<string>
    #include<bitset>
    #include<ctime>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<map>
    #include<set>
    #define Cpy(x,y) memcpy(x,y,sizeof(x))
    #define Set(x,y) memset(x,y,sizeof(x))
    #define FILE "4129"
    #define mp make_pair
    #define pb push_back
    #define RG register
    #define il inline
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<int>VI;
    typedef long long ll;
    typedef double dd;
    const int N=50010;
    const int M=10000010;
    const dd eps=1e-5;
    const int inf=2147483647;
    const ll INF=1ll<<60;
    const ll P=100000;
    il ll read(){
      RG ll data=0,w=1;RG char ch=getchar();
      while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
      if(ch=='-')w=-1,ch=getchar();
      while(ch<='9'&&ch>='0')data=data*10+ch-48,ch=getchar();
      return data*w;
    }
    
    il void file(){
      srand(time(NULL)+rand());
      freopen(FILE".in","r",stdin);
      freopen(FILE".out","w",stdout);
    }
    
    int n,q,o[N],a[N],q1,q2;
    int cal[N],cov,m,blk,be[N];
    int head[N],nxt[N<<1],to[N<<1],cnt;
    il void add(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;}
    struct node{int x,y,id,tim;}Q1[N],Q2[N];
    bool cmp(node u,node v){
      if(be[u.x]!=be[v.x])return be[u.x]<be[v.x];
      if(be[u.y]!=be[u.y])return be[u.y]<be[v.y];
      return u.tim<v.tim;
    }
    
    int fa[N],sz[N],dep[N],son[N],top[N],dfn[N],toc;
    void dfs1(int u,int ff){
      fa[u]=ff;dep[u]=dep[ff]+1;son[u]=0;sz[u]=1;
      for(RG int i=head[u];i;i=nxt[i]){
        RG int v=to[i];if(v==ff)continue;
        dfs1(v,u);sz[u]+=sz[v];
        if(sz[son[u]]<sz[v])son[u]=v;
      }
    }
    void dfs2(int u,int tp){
      top[u]=tp;dfn[u]=++toc;RG int bot=cov;
      if(son[u])dfs2(son[u],tp);
      if(cov-bot>=m){blk++;while(cov!=bot){be[cal[cov]]=blk;cov--;}}
      for(RG int i=head[u];i;i=nxt[i]){
        RG int v=to[i];if(v==son[u]||v==fa[u])continue;
        dfs2(v,v);
        if(cov-bot>=m){blk++;while(cov!=bot){be[cal[cov]]=blk;cov--;}}
      }
      cal[++cov]=u;
    }
    il int lca(int u,int v){
      while(top[u]!=top[v]){
        if(dep[top[u]]<dep[top[v]])swap(u,v);
        u=fa[top[u]];
      }
      return dep[u]<dep[v]?u:v;
    }
    
    int k,t[N],s[N],b[N],tot,ans[N];bool vis[N];
    il void upd(int u){
      if(a[u]>50000)return;
      if(a[u]){
        if(vis[u]&&t[a[u]]==1)s[b[a[u]]]++;
        if(!vis[u]&&!t[a[u]])s[b[a[u]]]--;
      }
      t[a[u]]+=(vis[u]?-1:1);vis[u]^=1;
    }
    il int calc(){
      if(!t[0])return 0;
      for(RG int i=1;i<=tot;i++)
        if(s[i])
          for(RG int j=(i-1)*k+1;j<=50000&&j<=i*k;j++)
    	if(!t[j])return j;
    }
    il void move(int u,int v){
      if(dep[u]<dep[v])swap(u,v);
      while(dep[u]!=dep[v])upd(u),u=fa[u];
      while(u!=v)upd(u),upd(v),u=fa[u],v=fa[v];
    }
    il void modify(int u,int v){if(vis[u])upd(u),a[u]=v,upd(u);a[u]=v;}
    
    int main()
    {
      n=read();q=read();m=pow(n,(0.6));k=250;tot=(50000-1)/k+1;
      for(RG int i=1;i<=n;i++)o[i]=a[i]=read();
      for(RG int i=1,u,v;i<n;i++){u=read();v=read();add(u,v);add(v,u);}
      for(RG int i=1;i<=50000;i++){b[i]=(i-1)/k+1;s[b[i]]++;}
      dfs1(1,0);dfs2(1,1);
      if(cov){blk++;while(cov){be[cal[cov]]=blk;cov--;}}
      for(RG int i=1,opt,x,y;i<=q;i++){
        opt=read();x=read();y=read();
        if(!opt)Q1[++q1]=(node){x,y,o[x],0},o[x]=y;
        else{if(dfn[x]<dfn[y])swap(x,y);q2++;Q2[q2]=(node){x,y,q2,q1};}
      }
    
      sort(Q2+1,Q2+q2+1,cmp);
      for(RG int i=1,t=0,x=1,y=1,l;i<=q2;i++){
        while(t<Q2[i].tim)t++,modify(Q1[t].x,Q1[t].y);
        while(Q2[i].tim<t)modify(Q1[t].x,Q1[t].id),t--;
        move(x,Q2[i].x);x=Q2[i].x;
        move(y,Q2[i].y);y=Q2[i].y;
        l=lca(x,y);upd(l);ans[Q2[i].id]=calc();upd(l);
      }
      for(RG int i=1;i<=q2;i++)printf("%d
    ",ans[i]);
      return 0;
    }
    
    
  • 相关阅读:
    leetcode第9题判断回文数
    leetcode整数反转第七题
    leetcode刷题两数之和
    找工作之旅
    C#和.Ne学习第五天
    C#和.Ne学习第四天
    C#和.Ne学习第三天
    C#和.Ne学习第二天
    C#和.Ne学习第一天
    从今天开始正事学习C#和.Net了
  • 原文地址:https://www.cnblogs.com/cjfdf/p/9709255.html
Copyright © 2020-2023  润新知