【BZOJ3307】雨天的尾巴

题解:

win下的10mb和linux下的好像不是很一样 明天再看看

求lca用的离线求,注意bz数组开2*n

这道题的线段树合并还是很好想的

我们只要把操作差分一下就好了

时间复杂度nlogn的

写代码用时:1:30

对拍+maker+调错=30

看到网上题解用的是树剖。。

我看了很久很久才理解。。

以前我用树剖都没有去理解它变成序列这个本质。。

树剖保证了区间的连续性,所以差分对于不在同一段的完全没有影响

所以树剖完了就直接变成序列问题,非常强势啊

明天补

这样是nlognlogn的

正解:

 

#include <bits/stdc++.h>
using namespace std;
#define IL inline
#define rint register int
const int N=1.1e5;
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||57<c)if(c=='-')f=-1;x=c^48;
    while(c=gc(),47<c&&c<58)x=(x<<3)+(x<<1)+(c^48);x*=f;
}
IL void maxa(int &x,int y)
  {
    if (x>y) return;
    else x=y;
  } 
  IL void mina(int &x,int y)
  {
    if (x<y) return;
    else x=y;
  }
  IL int max(int x,int y)
  {
     if (x>y) return(x); else return(y);
  }
  IL int min(int x,int y)
  {
     if (x<y) return(x); else return(y); 
  }
int n,m,fa[N],head[N],fi[N],root[N],cnt,cnt2,l,ans[N];
struct re{
  int a,b;
}a[N*2],b[N],c[N];
IL void arr(int x,int y)
{
  a[++l].a=head[x];
  a[l].b=y;
  head[x]=l;
}
int id[N],dy[N],bz[21][N*2],pos[N],vt[N],fdy[N];
vector <int> ve1[N],ve2[N];
void dfs(int x)
{
  id[x]=++cnt;
  dy[cnt]=x;
  bz[0][++cnt2]=id[x];
  pos[x]=cnt2;
  int u=head[x];
  while (u)
  {
    int v=a[u].b;
    if (v!=fa[x])
    {
      fa[v]=x;
      dfs(v);
      bz[0][++cnt2]=id[x];
    }
    u=a[u].a;
  }
}
IL void swap(int &x,int &y)
{
  int z=x; x=y; y=z;
}
IL int lca(int x,int y)
{
  if (x==y) return(x);
  x=pos[x],y=pos[y];
  if (x>y) swap(x,y);
  int z=log2(y-x+1);
  return(dy[min(bz[z][x],bz[z][y-(1<<z)+1])]);
}
struct segementree
{
  int cnt;
  int v[N*20],p[N*20],ls[N*20],rs[N*20];
  segementree() { cnt=0; }
  #define mid ((h+t)/2)
  IL void updata(int x)
  {
     v[x]=max(v[ls[x]],v[rs[x]]);
     if (v[ls[x]]>v[rs[x]]||(v[ls[x]]==v[rs[x]]&&p[ls[x]]<p[rs[x]]))
        p[x]=p[ls[x]];
     else p[x]=p[rs[x]];
  }
  void change(int &x,int h,int t,int pos,int k)
  {
    if (!x) x=++cnt;
    if (h==t)
    { 
      v[x]+=k; p[x]=pos; return;
    }
    if (pos<=mid) change(ls[x],h,mid,pos,k);
    else change(rs[x],mid+1,t,pos,k);
    updata(x);
  }
  int merge(int x,int y,int h,int t)
  {
    if (!x||!y) return(x^y);
    ls[x]=merge(ls[x],ls[y],h,mid);
    rs[x]=merge(rs[x],rs[y],mid+1,t);
    if (h==t) v[x]+=v[y];
    else updata(x);
    return(x);
  }
}se1;
void dfs2(int x)
{
  rint u=head[x];
  while (u)
  {
    rint v=a[u].b;
    if(v!=fa[x])
    {
      dfs2(v);
      root[x]=se1.merge(root[x],root[v],1,m);
    }
    u=a[u].a;
  }
  for (rint i=0;i<ve1[x].size();i++)
    se1.change(root[x],1,m,ve1[x][i],1);
  for (rint i=0;i<ve2[x].size();i++)
    se1.change(root[x],1,m,ve2[x][i],-1);
  if(!se1.v[root[x]]) ans[x]=0;
  else ans[x]=se1.p[root[x]];
}
IL bool cmp(re x,re y)
{
  return(x.a<y.a);
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  read(n); read(m); 
  int x,y;
  for (int i=1;i<=n-1;i++)
  {
    read(x); read(y); arr(x,y); arr(y,x); 
  }
  dfs(1);
  for (rint i=1;i<=20;i++)  
    for (rint j=1;j<=cnt2;j++)
      if ((1<<(i-1))+j-1<=cnt2)
        bz[i][j]=min(bz[i-1][j],bz[i-1][j+(1<<(i-1))]);
  for( int i=1;i<=m;i++)
  {
    read(c[i].a); read(c[i].b);
    read(b[i].a); b[i].b=i; 
  }
  sort(b+1,b+m+1,cmp);
  b[0].a=1e9;
  int cnt3=0;
  for (int i=1;i<=m;i++)
  {
    if (b[i].a!=b[i-1].a)
    {
      cnt3++;
      fdy[cnt3]=b[i].a;
    }
    vt[b[i].b]=cnt3;
  }
  for (int i=1;i<=m;i++)
  {
    int x=c[i].a,y=c[i].b,z=vt[i];
    // cout<<x<<" "<<y<<" "<<z<<" "; 
    int xx=lca(x,y);
    //cout<<xx<<endl;
    ve1[x].push_back(z);
    ve1[y].push_back(z);
    ve2[xx].push_back(z);
    ve2[fa[xx]].push_back(z);
  }
  dfs2(1);
  for (int i=1;i<=n;i++) 
  {
    printf("%d\n",fdy[ans[i]]);
  }
  return 0; 
}
//离散化 

 

 

 

拍:

#include <bits/stdc++.h>
using namespace std;
const int N=1e3;
int v[N][N];
int head[N],n,m,l;
struct re{
  int a,b;
}a[N*2];
void arr(int x,int y)
{
  a[++l].a=head[x];
  a[l].b=y;
  head[x]=l;
}
int cnt=0,id[N],dy[N],fa[N];
void dfs(int x,int fa1)
{
  int u=head[x];
  id[x]=++cnt;
  dy[cnt]=x;
  while (u)
  {
    int v=a[u].b;
    if (v!=fa1) fa[v]=x,dfs(v,x);
    u=a[u].a;
  }
}
const int INF=1e9;
bool pd(int x,int y)
{
  while (x!=y&&x) x=fa[x];
  if(x==y) return(1); else return(0);
}
int lca(int x,int y)
{
  int ans=0;
  for (int i=1;i<=n;i++)
    if (pd(x,i)&&pd(y,i)) ans=max(ans,id[i]);
  return(dy[ans]);
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("2.out","w",stdout);
  cin>>n>>m;
  for (int i=1;i<=n-1;i++)
  {
    int x,y;
    cin>>x>>y;
    arr(x,y); arr(y,x);
  }
  dfs(1,0);
  for (int i=1;i<=m;i++)
  {
    int x,y,z;
    cin>>x>>y>>z;
    int xx=lca(x,y);
    for (int i=x;i!=fa[xx];i=fa[i]) v[i][z]++;
    for (int i=y;i!=fa[xx];i=fa[i]) v[i][z]++;
    v[xx][z]--;
  }
  for (int i=1;i<=n;i++)
  {
    int ans=0,ans2=0;
    for (int j=1;j<=100;j++)
      if(v[i][j]>ans) ans=v[i][j],ans2=j;
    cout<<ans2<<endl;
  }
  return 0;
} 

数据:

#include <bits/stdc++.h>
using namespace std;
int main()
{
  freopen("1.in","w",stdout);
  int n=100000,m=100000;
  cout<<n<<" "<<m<<endl;
  srand(time(0));
  for (int i=2;i<=n;i++)
  {
    int x=rand()%(i-1)+1;
    cout<<x<<" "<<i<<endl; 
  }
  for (int i=1;i<=m;i++)
  {
    int x=rand()%n+1,y=rand()%n+1,z=rand()%1000000000+1;
    cout<<x<<" "<<y<<" "<<z<<endl; 
  }
}

 

posted @ 2018-05-21 00:28  尹吴潇  阅读(152)  评论(0编辑  收藏  举报