题解:
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 ",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; } }