[SDOI2018]原题识别

题解:

。。感觉挺烦得 而且我都没有注意到树随机这件事情。。

就写个30分的莫队。。

 

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (int i=h;i<=t;i++)
#define dep(i,t,h) for (int i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
namespace IO{
    char ss[1<<24],*A=ss,*B=ss;
    IL char gc()
    {
        return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
    }
    template<class T>void read(T &x)
    {
        rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
        while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
    }
    char sr[1<<24],z[20]; int Z,CC=-1;
    template<class T>void wer(T x)
    {
        if (x<0) sr[++CC]='-',x=-x;
        while (z[++Z]=x%10+48,x/=10);
        while (sr[++CC]=z[Z],--Z); 
    }
    IL void wer1()
    {
        sr[++CC]=' ';
    }
    IL void wer2()
    {
        sr[++CC]='\n';
    }
    template<class T>IL void mina(T &x,T y) { if (x>y) x=y;}
    template<class T>IL void maxa(T &x,T y) { if (x<y) x=y;}
    template<class T>IL T MIN(T x,T y){return x<y?x:y;}
    template<class T>IL T MAX(T x,T y){return x>y?x:y;}
};
using namespace IO;
unsigned int SA, SB, SC;
unsigned int rng61(){
    SA ^= SA << 16;
    SA ^= SA >> 5;
    SA ^= SA << 1;
    unsigned int t = SA;
    SA = SB;
    SB = SC;
    SC ^= t ^ SA;
    return SC;
}
const int N=4.1e5;
int l,head[N],n,m,c[N];
struct re{
    int a,b,c,d;
}e[N],a[N];
IL void arr(int x,int y)
{
    e[++l].a=head[x];
    e[l].b=y;
    head[x]=l;
}
IL void addedge(int x,int y)
{
    arr(x,y); arr(y,x);
}
int p;
void gen(){
    cin>>n>>p>>SA>>SB>>SC;
    l=0; me(head);
        for(int i = 2; i <= p; i++)
    addedge(i - 1, i);
    for(int i = p + 1; i <= n; i++)
    addedge(rng61() % (i - 1) + 1, i);
    for(int i = 1; i <= n; i++)
    c[i] = rng61() % n + 1;
}
int cnt,dfn1[N],dfn2[N],dep[N],block,num,pos[N];
int bz[21][N],ans[N],jl[N],ans2,po[N],b[N];
void dfs(int x,int y)
{
    bz[0][x]=y; dep[x]=dep[y]+1; dfn1[x]=++cnt;
    b[cnt]=x;
    for (rint u=head[x];u;u=e[u].a)
    {
        int v=e[u].b;
        if (v!=y) dfs(v,x);
    }
    dfn2[x]=++cnt; b[cnt]=x;
}
void change(int x,int k)
{
    x=b[x]; int o;
    jl[x]+=k;
    if (jl[x]==1) o=1; else o=-1;
    if (ans[c[x]]>0) ans2--;
    ans[c[x]]+=o;
    if (ans[c[x]]>0) ans2++;
}
int lca(int x,int y)
{
    if (dep[x]<dep[y]) swap(x,y);
    dep(i,20,0)
      if (dep[bz[i][x]]>=dep[y])
        x=bz[i][x];
    if (x==y) return(x);
    dep(i,20,0)
      if (bz[i][x]!=bz[i][y])
        x=bz[i][x],y=bz[i][y];
    return bz[0][x];
}
bool cmp(re x,re y)
{
    int k1=pos[x.a],k2=pos[y.a];
    return k1<k2||(k1==k2&&x.b<y.b);
}
int main()
{
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    ios::sync_with_stdio(false);
    int T,m;
    cin>>T;
    while (T--)
    {
        me(ans); me(jl); cnt=0; ans2=0;
        gen();
        dfs(1,0); 
        rep(i,1,20)
          rep(j,1,n)
            bz[i][j]=bz[i-1][bz[i-1][j]];
        cin>>m;
        rep(i,1,m)
        {
            int kk,x,y;
         cin>>kk>>x>>y;
          int k=lca(x,y);
          if (k!=x&&k!=y)
          {
              if (dfn1[x]>dfn1[y]) swap(x,y);
              a[i].a=dfn2[x],a[i].b=dfn1[y]; 
                a[i].c=k;
          } else
          {
              if (y==k) swap(x,y);
              a[i].a=dfn1[x],a[i].b=dfn1[y];
              a[i].c=0;
          }
          a[i].d=i;
        }
        int n1=2*n;
        block=sqrt(n1);
        num=(n1-1)/block+1;
        rep(i,1,n1) pos[i]=(i-1)/block+1;
        sort(a+1,a+m+1,cmp);
        rep(i,1,m)
        {
            if (a[i].a<=a[i-1].a)
          rep(j,a[i].a,a[i-1].a-1) change(j,1);    
            if (a[i].b>=a[i-1].b)
                rep(j,a[i-1].b+1,a[i].b) change(j,1);
            if (a[i].a>a[i-1].a)
                rep(j,a[i-1].a,a[i].a-1) change(j,-1);
            if (a[i].b<a[i-1].b)
              rep(j,a[i].b+1,a[i-1].b) change(j,-1);    
            if (a[i].c)
            {
                if (ans[c[a[i].c]]==0) po[a[i].d]=ans2+1;
                else po[a[i].d]=ans2;
            } else po[a[i].d]=ans2;
        }
        rep(i,1,m) wer(po[i]),wer2();
    }
    fwrite(sr,1,CC+1,stdout);
    return 0;
}

 

转载于:https://www.cnblogs.com/yinwuxiao/p/10044288.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值