四连测Day1
题目:链接: https://pan.baidu.com/s/163ycV64ioy7uML7AvRDTGw 密码: p86i
T1:
倍增求LCA,minn数组记录最小值
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline long long read() { long long f=1,ans=0;char c; while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();} while(c>=\'0\'&&c<=\'9\'){ans=ans*10+c-\'0\';c=getchar();} return ans*f; } long long q,a[500001],fa[500001][23],minn[500001][23]; struct node{ long long x;long long y; long long nex; }ss[1000001]; long long head[500001]; long long cnt=1; void add(long long a,long long b) { ss[cnt].x=a,ss[cnt].y=b; ss[cnt].nex=head[a],head[a]=cnt++; return; } long long deep[500001]; void dfs(long long f,long long fath) { deep[f]=deep[fath]+1; minn[f][0]=min(a[f],a[fath]); fa[f][0]=fath; for(long long i=1;(1<<i)<=deep[f];i++) fa[f][i]=fa[fa[f][i-1]][i-1],minn[f][i]=min(minn[f][i-1],minn[fa[f][i-1]][i-1]); for(long long i=head[f];i!=-1;i=ss[i].nex) if(ss[i].y!=fath) dfs(ss[i].y,f); } long long n,m,s; long long lca(long long u,long long v) { long long sry=min(a[u],a[v]); // cout<<sry<<endl; if(deep[u]<deep[v]) swap(u,v); for(long long i=22;i>=0;i--) if(deep[u]-(1<<i)>=deep[v]) sry=min(sry,minn[u][i]),u=fa[u][i]; // cout<<sry<<" "<<u<<" "<<v<<endl; if(u==v) return sry; for(long long i=22;i>=0;i--) { if(fa[u][i]==fa[v][i]) continue; else { sry=min(sry,minn[u][i]),sry=min(sry,minn[v][i]); u=fa[u][i],v=fa[v][i]; } } // cout<<fa[u][0]<<endl; return min(sry,a[fa[u][0]]); } int main() { memset(head,-1,sizeof(head)); n=read(),q=read(); for(long long i=1;i<=n;i++) a[i]=read(); for(long long i=1;i<n;i++) { long long u=read(),v=read(); add(u,v),add(v,u); } dfs(1,0); for(long long i=1;i<=q;i++) { long long u=read(),v=read(); printf("%d\n",lca(u,v)); // return 0; } }/* 5 5 8 100 502 9 3 2 4 4 1 1 3 1 5 3 5 1 5 2 3 2 1 3 4 */
View Code
T2:
桶排序,因为告诉你a[i]最大为1048575,异或和为a[i]^a[i+1]^……a[j],拿sort会超时
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> using namespace std; inline int read() { int f=1,ans=0;char c; while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();} while(c>=\'0\'&&c<=\'9\'){ans=ans*10+c-\'0\';c=getchar();} return f*ans; } int a[1048576],x[50005001]; int n,s[10001]; int main() { n=read();int q=read(); for(int i=1;i<=n;i++) s[i]=read(); for(int i=1;i<=n;i++) { int sum=0; for(int j=i;j<=n;j++) sum^=s[j],a[sum]++; } int cnt=0; for(int i=0;i<=1048575;i++) while(a[i]!=0) x[++cnt]=i,a[i]--; for(int i=1;i<=q;i++) { int xx=read(); printf("%d\n",x[xx]); } }
View Code
T3:
先将每一个点想成一个区间,r[i]表示i的祖先节点所在区间的最右号,l同理,f为祖先,j=r[find(j)]+1表示因为j号节点的区间右侧为r[find(j)],所以可得。
将边权从小到大排序,区间覆盖即可
#include<iostream> #include<algorithm> #include<cmath> #include<cstring> #include<cstdio> using namespace std; inline int read() { int f=1,ans=0;char c; while(c<\'0\'||c>\'9\'){if(c==\'-\')f=-1;c=getchar();} while(c>=\'0\'&&c<=\'9\'){ans=ans*10+c-\'0\';c=getchar();} return f*ans; } int n,m; int f[100001],r[100001],l[100001]; int find(int x) { if(f[x]==x) return x; return f[x]=find(f[x]); } struct node{ int ll,rr,v; }x[100001]; bool cmp(node xx,node yy) { return xx.v<yy.v; } int ans,sum; void merge(int x1,int x2) { int t1=find(x1),t2=find(x2); f[t2]=t1; l[t1]=min(l[t1],l[t2]); r[t1]=max(r[t1],r[t2]); } int main() { n=read(),m=read(); for(int i=1;i<=n;i++) f[i]=l[i]=r[i]=i; for(int i=1;i<=m;i++) x[i].ll=read(),x[i].rr=read(),x[i].v=read(); sort(x+1,x+m+1,cmp); for(int i=1;i<=m;i++) { int j=r[find(x[i].ll)]+1; while(j<=x[i].rr) { ans++; sum+=x[i].v; merge(x[i].ll,j); j=r[find(j)]+1; } if(ans==n-1) { printf("%d\n",sum); return 0; } } cout<<-1; } /* 5 4 1 2 1 3 4 2 3 5 3 1 4 1 */
View Code