3237: [Ahoi2013]连通图 线段树分治

Posted yinwuxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了3237: [Ahoi2013]连通图 线段树分治相关的知识,希望对你有一定的参考价值。

题解:

线段树分治裸题

apio t1是这个所以就学习了一下

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
struct re{
    int x,y;
}a[N*2];
int b[N+20][5],cnt,now,n,m,k;
int ls[N*15],rs[N*15],data[N*15],last[N+20];
int ph[N*4],pt[N*4],count2[N+20],f[N];
bool ft[N+20];
vector<int> ve[N];
#define mid (ph[x]+pt[x])/2
void change(int last,int &now,int h,int t,int goal,int goal2)
{
    now=++cnt;
    if (h==t)
    { 
      data[now]=goal2;
      return;
  }
    ls[now]=ls[last];
    rs[now]=rs[last];
    int mid2=(h+t)/2;
    if (goal<=mid2) change(ls[last],ls[now],h,mid2,goal,goal2);
    else change(rs[last],rs[now],mid2+1,t,goal,goal2);
}
int query(int x,int h,int t,int goal)
{
    if (h==t) return(data[x]);
    int mid2=(h+t)/2;
    if (goal<=mid2) return(query(ls[x],h,mid2,goal));
    else return(query(rs[x],mid2+1,t,goal));
}
void build(int x,int h,int t)
{
    ph[x]=h; pt[x]=t;
    if (h==t) return;
    build(x*2,h,mid); build(x*2+1,mid+1,t);
}
void insert(int x,int h,int t,int goal)
{
    if (h<=ph[x]&&pt[x]<=t)
    { 
      ve[x].push_back(goal);
      return;
  }
  if (h<=mid) insert(x*2,h,t,goal);
  if (mid<t) insert(x*2+1,h,t,goal);
}
int find(int root,int x)
{
  int y=query(root,1,N,x);
    if (y==x) return(x);
    else return(find(root,y));
}
void dfs(int x,int h,int t,int ans)
{
    stack<re> s;
    last[x]=now;
    int len=ve[x].size();
    for (int i=0;i<len;i++)
    {
        int x1=a[ve[x][i]].x,x2=a[ve[x][i]].y;
        int x11=find(now,x1),x22=find(now,x2);
        if (x11!=x22)
        {
            if (count2[x11]>count2[x22]) swap(x11,x22);
            change(now,now,1,N,x11,x22);
            s.push(re{x22,count2[x22]});
            count2[x22]+=count2[x11];
            ans++;
        }
    }
    if (h==t)
    {
        if (ans==n-1) ft[h]=1; else ft[h]=0;
    } else
    {
      dfs(x*2,h,(h+t)/2,ans); 
        dfs(x*2+1,(h+t)/2+1,t,ans);
  }
  while (!s.empty())
  {
      re x=s.top(); s.pop();
    count2[x.x]=x.y;
    }
    now=last[x];
}
int main()
{
    freopen("noi.in","r",stdin);
    freopen("noi.out","w",stdout);
    cin>>n>>m;
    for (int i=1;i<=m;i++)
    {
        cin>>a[i].x>>a[i].y;
    }
    cin>>k;
    for (int i=1;i<=n;i++) f[i]=1;
    for (int i=1;i<=n;i++)
    {
      change(now,now,1,N,i,i);
      count2[i]=1;
  }
  build(1,1,k);
    for (int i=1;i<=k;i++)
    {
        int nown;
        cin>>nown;
        for (int j=1;j<=nown;j++)
        {
          cin>>b[i][j];
          if (i-1>=f[b[i][j]])
          {
            insert(1,f[b[i][j]],i-1,b[i][j]);
          }
          f[b[i][j]]=i+1;
      }
    }
    for (int i=1;i<=m;i++)
      if (f[i]<=k)
          insert(1,f[i],k,i);
    dfs(1,1,k,0);
    for (int i=1;i<=k;i++)
      if (ft[i]==1) cout<<"Connected"<<endl;
      else cout<<"Disconnected"<<endl;
    return 0;
}

 

以上是关于3237: [Ahoi2013]连通图 线段树分治的主要内容,如果未能解决你的问题,请参考以下文章

bzoj3237 [Ahoi2013]连通图

bzoj3237 Ahoi2013—连通图

BZOJ3237: [Ahoi2013]连通图

Codeforces 938G 线段树分治 线性基 可撤销并查集

bzoj 3236: [Ahoi2013]作业(缺线段树)

线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)