A. Colourful Graph

可以在$2n$步之内实现交换任意两个点的颜色,然后就可以构造出方案。

  1. #include <bits/stdc++.h>
  2. using namespace std ;
  3. typedef long long LL;
  4. const int mod=1e9+7,Maxn=222;
  5. const LL Inf=1LL<<60;
  6. int n,m,K;
  7. int col[Maxn],col2[Maxn];
  8. int done[Maxn],pre[Maxn];
  9. vector<int>G[Maxn];
  10. vector<int> way[102][102];//i->j
  11. int fst[222];
  12. void bfs(int st){
  13. for(int i=1;i<=n;i++)done[i]=i==st?1:0;
  14. queue<int>q;
  15. q.push(st);
  16. while(!q.empty()){
  17. int u=q.front();q.pop();
  18. for(int i=0;i<G[u].size();i++){
  19. int v=G[u][i];if(done[v])continue;
  20. done[v]=1;
  21. pre[v]=u;
  22. q.push(v);
  23. }
  24. }
  25. for(int i=1;i<=n;i++){
  26. int u=i;
  27. way[st][i].clear();
  28. for(;u!=st;u=pre[u])way[st][i].push_back(u);
  29. way[st][i].push_back(st);
  30. reverse(way[st][i].begin(),way[st][i].end());
  31. }
  32. }
  33. void pt(){
  34. for(int i=1;i<=n;i++)printf("%d%c",col[i],i==n?'\n':' ');
  35. }
  36. void swp(int st,int ed,int ty){
  37. vector<int>tmp=way[st][ed];
  38. for(int i=0;i<tmp.size()-1;i++){
  39. if(i==tmp.size()-2){
  40. if(ty)col[tmp[i+1]]=col[tmp[i]];
  41. else swap(col[tmp[i+1]],col[tmp[i]]);
  42. }
  43. else swap(col[tmp[i]],col[tmp[i+1]]);
  44. pt();
  45. }
  46. for(int i=tmp.size()-2;i>0;i--){
  47. swap(col[tmp[i]],col[tmp[i-1]]);
  48. pt();
  49. }
  50. }
  51. void solve () {
  52. for(int i=1;i<=n;i++)scanf("%d",col+i),G[i].clear();
  53. for(int i=1;i<=n;i++)scanf("%d",col2+i);
  54. for(int i=0;i<m;i++){
  55. int u,v;scanf("%d%d",&u,&v);
  56. G[u].push_back(v);
  57. G[v].push_back(u);
  58. }
  59. //puts("ok");
  60. bool flag=1;
  61. for(int i=1;i<=n;i++){
  62. int t=0;
  63. for(int j=1;j<=n;j++)if(col2[i]==col[j]){t=1;break;}
  64. if(!t){flag=0;break;}
  65. }
  66. if(!flag){
  67. puts("Impossible");
  68. return;
  69. }
  70. pt();
  71. for(int i=1;i<=n;i++)bfs(i);
  72.  
  73. memset(fst,0,sizeof fst);
  74. for(int i=1;i<=n;i++){
  75. if(!fst[col2[i]]){
  76. fst[col2[i]]=i;
  77. if(col[i]==col2[i])continue;
  78. for(int j=1;j<=n;j++){
  79. if(col[j]==col2[i]){
  80. swp(j,i,0);
  81. break;
  82. }
  83. }
  84. }
  85. }
  86. for(int i=1;i<=n;i++){
  87. if(col[i]!=col2[i])swp(fst[col2[i]],i,1);
  88. }
  89. }
  90.  
  91. int main () {
  92. while ( ~scanf ( "%d%d%d" , &n,&m,&K ) ) solve () ;
  93. return 0 ;
  94. }

  

B. Doors

答案就是这些折线之间距离的最小值除以2。

  1. #include<cstdio>
  2. #include<cmath>
  3. #include<algorithm>
  4. using namespace std;
  5.  
  6. double R,L,W,Alpha,Beta;
  7. int Case;
  8.  
  9. const double pi=acos(-1.0),eps=1e-9,inf=10000.0;
  10.  
  11. int sgn(double x){
  12. if(x<-eps)return -1;
  13. if(x>eps)return 1;
  14. return 0;
  15. }
  16. struct P{
  17. double x,y;
  18. P(){x=y=0;}
  19. P(double _x,double _y){x=_x,y=_y;}
  20. P operator+(P v){return P(x+v.x,y+v.y);}
  21. P operator-(P v){return P(x-v.x,y-v.y);}
  22. double operator*(P v){return x*v.x+y*v.y;}
  23. double len(){return hypot(x,y);}
  24. };
  25. double cross(P a,P b){return a.x*b.y-a.y*b.x;}
  26.  
  27. double dist_point_to_segment(P p,P a,P b){
  28. if(sgn((p-a)*(b-a))>=0&&sgn((p-b)*(a-b))>=0)
  29. return fabs(cross(p-a,b-a))/(b-a).len();
  30. return min((p-a).len(),(p-b).len());
  31. }
  32.  
  33. double cal(P a,P b,P c,P d){
  34. return min(min(dist_point_to_segment(a,c,d),
  35. dist_point_to_segment(b,c,d)),
  36. min(dist_point_to_segment(c,a,b),
  37. dist_point_to_segment(d,a,b)));
  38. }
  39.  
  40. double solve(){
  41. P A(-inf,W),B(0,W);
  42. P D(L,W),E(inf,W);
  43. P G(L,0),H(inf,0);
  44. Alpha=pi-Alpha,Beta=pi-Beta;
  45. P C=D+P(cos(Alpha)*L,sin(Alpha)*L);
  46. P F=G+P(cos(Beta)*L,sin(Beta)*L);
  47. double ans=min(L,W);
  48. ans=min(ans,cal(A,B,C,D));
  49. ans=min(ans,cal(C,D,F,G));
  50. ans=min(ans,cal(D,E,F,G));
  51. ans/=2.0;
  52. ans=min(ans,R);
  53. ans=max(ans,0.0);
  54. return ans;
  55. }
  56.  
  57. int main(){
  58. scanf("%lf%lf%lf",&R,&L,&W);
  59. scanf("%d",&Case);
  60. while(Case--){
  61. scanf("%lf%lf",&Alpha,&Beta);
  62. printf("%.9f\n",solve());
  63. }
  64. return 0;
  65. }

  

C. Peak Tower

求出所有线段相交的时刻,在相邻时刻里三分答案即可。时间复杂度$O(n^4\log n)$。

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cmath>
  4. #include<vector>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. const int N=2000;
  9. const double eps=1e-9;
  10. double W,H,E,ans=1e9;
  11. int n,i,j;
  12. struct Rec{
  13. double w,h,sx,sy,vx,vy;
  14. void read(){
  15. scanf("%lf%lf%lf%lf%lf%lf",&w,&h,&sx,&sy,&vx,&vy);
  16. }
  17. }a[N];
  18. int sgn(double x){
  19. if(x<-eps)return -1;
  20. if(x>eps)return 1;
  21. return 0;
  22. }
  23. int m,cnt;
  24. double vipy[N];
  25. int cov[N];
  26. double ct[1000000];
  27. int cntt;
  28. struct Ev{
  29. double x,l,r;int p;
  30. Ev(){}
  31. Ev(double _x,double _l,double _r,int _p){x=_x,l=_l,r=_r,p=_p;}
  32. }e[N];
  33. inline bool cmp(const Ev&a,const Ev&b){
  34. return a.x<b.x;
  35. }
  36. double cal(double Time){
  37. //if(Time<-eps||Time>E+eps)return;
  38. int i,j;
  39. m=0;
  40. for(i=1;i<=n;i++){
  41. double xl=a[i].sx+a[i].vx*Time,
  42. xr=xl+a[i].w,
  43. yl=a[i].sy+a[i].vy*Time,
  44. yr=yl+a[i].h;
  45. xl=min(max(xl,0.0),W);
  46. xr=min(max(xr,0.0),W);
  47. yl=min(max(yl,0.0),H);
  48. yr=min(max(yr,0.0),H);
  49. //printf("%.8f %.8f %.8f %.8f\n",xl,xr,yl,yr);
  50. if(xl+eps>xr||yl+eps>yr)continue;
  51. vipy[++m]=yl;
  52. e[m]=Ev(xl,yl,yr,1);
  53. vipy[++m]=yr;
  54. e[m]=Ev(xr,yl,yr,-1);
  55. }
  56. double ret=0;
  57. if(!m){
  58. //printf("fuck %.8f %.8f\n",Time,0.0);
  59. ans=0;
  60. return 0;
  61. }
  62. sort(vipy+1,vipy+m+1);
  63. sort(e+1,e+m+1,cmp);
  64. for(i=1;i<m;i++)cov[i]=0;
  65. for(i=1;i<=m;i++){
  66. if(i>1){
  67. for(j=1;j<m;j++){
  68. if(cov[j]>0)ret+=(vipy[j+1]-vipy[j])*(e[i].x-e[i-1].x);
  69. }
  70. }
  71. if(ret>ans)return ret;
  72. double l=e[i].l,r=e[i].r;
  73. //printf("ev %.8f %.8f %.8f %d\n",e[i].x,l,r,e[i].p);
  74. for(j=1;j<m;j++){
  75. double A=vipy[j],B=vipy[j+1];
  76. if(sgn(A-l)>=0&&sgn(B-r)<=0){
  77. cov[j]+=e[i].p;
  78. }
  79. }
  80. }
  81. //printf("%.8f %.8f\n",Time,ret);
  82. ans=min(ans,ret);
  83. return ret;
  84. }
  85. inline bool check(double Time){
  86. if(Time<-eps||Time>E+eps)return 0;
  87. return 1;
  88. }
  89. void deal(double A,double B,double C,double D){
  90. A-=C;
  91. B-=D;
  92. A=-A;
  93. if(!sgn(B))return;
  94. if(check(A/B))ct[++cntt]=A/B;
  95. }
  96. void search(double l,double r){
  97. cal(r);
  98. double m1,m2,s1,s2;
  99. int step=0;
  100. while(l+1e-5<r&&step++<10){
  101. m1=l+(r-l)/3.0;
  102. m2=r-(r-l)/3.0;
  103. s1=cal(m1);
  104. s2=cal(m2);
  105. if(s1<s2)r=m2-eps;else l=m1+eps;
  106. }
  107. }
  108. int main(){
  109. scanf("%d%lf%lf%lf",&n,&W,&H,&E);
  110. for(i=1;i<=n;i++)a[i].read();
  111. ct[++cntt]=0;
  112. ct[++cntt]=E;
  113. a[n+1].w=W;
  114. a[n+1].h=H;
  115. for(i=1;i<=n+1;i++)
  116. for(j=i+1;j<=n+1;j++){
  117. deal(a[i].sx ,a[i].vx,a[j].sx ,a[j].vx);
  118. deal(a[i].sx+a[i].w,a[i].vx,a[j].sx ,a[j].vx);
  119. deal(a[i].sx ,a[i].vx,a[j].sx+a[j].w,a[j].vx);
  120. deal(a[i].sx+a[i].w,a[i].vx,a[j].sx+a[j].w,a[j].vx);
  121.  
  122. deal(a[i].sy ,a[i].vy,a[j].sy ,a[j].vy);
  123. deal(a[i].sy+a[i].h,a[i].vy,a[j].sy ,a[j].vy);
  124. deal(a[i].sy ,a[i].vy,a[j].sy+a[j].h,a[j].vy);
  125. deal(a[i].sy+a[i].h,a[i].vy,a[j].sy+a[j].h,a[j].vy);
  126. }
  127. //cal(5);
  128. sort(ct+1,ct+cntt+1);
  129. cal(0);
  130. for(i=1;i<=cntt;i++)if(ct[i]>ct[i-1]+eps){
  131. search(ct[i-1],ct[i]);
  132. }
  133. printf("%.10f",ans);
  134. }

  

D. Peak Tram

每个位置最多$O(n^2)$种可能的高度,然后DP即可。

  1. #include <bits/stdc++.h>
  2. using namespace std ;
  3. typedef long long LL;
  4. const int mod=1e9+7,Maxn=71;
  5. const LL Inf=1LL<<60;
  6. vector<LL>V;
  7. LL p[Maxn],c[Maxn];
  8. LL dp[2][142*71][71];
  9. LL pre[2][142*71][71];
  10. int getid(LL x){
  11. return lower_bound(V.begin(),V.end(),x)-V.begin();
  12. }
  13. int n,K;
  14. int tot;
  15. void init(int cs){
  16. for(int i=0;i<tot;i++){
  17. for(int j=0;j<=K;j++)dp[cs][i][j]=Inf;
  18. }
  19. }
  20. void calpre(int cs){
  21. for(int i=0;i<tot;i++){
  22. for(int j=0;j<=K;j++){
  23. pre[cs][i][j]=dp[cs][i][j];
  24. if(i)pre[cs][i][j]=min(pre[cs][i-1][j],pre[cs][i][j]);
  25. }
  26. }
  27. }
  28. inline void up(LL &x,LL y){if(x>y)x=y;}
  29. void solve () {
  30. V.clear();
  31. LL tp=0;
  32. V.push_back(tp);
  33. for(int i=1;i<=n;i++){
  34. scanf("%lld%lld",p+i,c+i);
  35. for(int j=-n;j<=n;j++)if(p[i]+j>0)V.push_back(p[i]+j);
  36. }
  37. sort(V.begin(),V.end());
  38. V.erase(unique(V.begin(),V.end()),V.end());
  39. tot=V.size();
  40. int cs=0;
  41. init(cs);
  42. dp[cs][0][0]=0;
  43. calpre(cs);
  44. for(int i=1;i<=n;i++){
  45. init(cs^1);
  46. //bubeikanjian
  47. int tid=getid(p[i]);
  48. for(int j=1;j<tot;j++){
  49. LL cost=0;
  50. if(j<tid){
  51. cost=abs(V[j]-p[i])*c[i];
  52. }
  53. for(int k=0;k<=K;k++){
  54. up(dp[cs^1][j][k],dp[cs][j][k]+cost);
  55. }
  56. }
  57. //kanjian
  58. for(int j=1;j<tot;j++){
  59. LL cost=abs(V[j]-p[i])*c[i];
  60. for(int k=1;k<=K;k++){
  61. up(dp[cs^1][j][k],pre[cs][j-1][k-1]+cost);
  62. up(dp[cs^1][j][k],pre[cs][j-1][k]+cost);
  63. }
  64. }
  65. calpre(cs^1);
  66. cs^=1;
  67. }
  68. LL ans=pre[cs][tot-1][K];
  69. printf("%lld\n",ans);
  70. }
  71.  
  72. int main () {
  73. while ( ~scanf ( "%d%d" , &n,&K ) ) solve () ;
  74. return 0 ;
  75. }

  

E. Perfect k-ary Tree

换根树形DP,需要记录树的高度,但是因为是满$k$叉树,因此树高是$O(\log n)$级别的。

  1. #include <bits/stdc++.h>
  2. using namespace std ;
  3. typedef long long LL;
  4. const int mod=1e9+7,Maxn=100020;
  5. int dp1[19][Maxn];
  6. int n,K;
  7. vector<int>G[Maxn];
  8. int f[2][6];
  9. inline void up(int &x,int y){x+=y;if(x>=mod)x-=mod;}
  10. void dfs1(int u,int p){
  11. for(int i=0;i<G[u].size();i++){
  12. int v=G[u][i];if(v==p)continue;
  13. dfs1(v,u);
  14. }
  15. dp1[0][u]=1;
  16. //printf("u=%d\n",u);
  17. for(int i=1;(1<<i)<=n;i++){
  18. int cs=0;
  19. memset(f[cs],0,sizeof f[cs]);
  20. f[cs][0]=1;
  21. for(int j=0;j<G[u].size();j++){
  22. int v=G[u][j];if(v==p)continue;
  23. memset(f[cs^1],0,sizeof f[cs^1]);
  24. for(int k=0;k<=K;k++){
  25. if(!f[cs][k])continue;
  26. if(k<K)up(f[cs^1][k+1],1LL*f[cs][k]*dp1[i-1][v]%mod);
  27. up(f[cs^1][k],f[cs][k]);
  28. }
  29. cs^=1;
  30. }
  31. dp1[i][u]=f[cs][K];
  32. }
  33. //for(int i=0;(1<<i)<=n;i++)printf("%d ",dp1[i][u]);puts("");
  34. }
  35. int dp2[19][Maxn];
  36. int pre[Maxn][6],suf[Maxn][6];
  37. int ans;
  38. void dfs2(int u,int p){
  39. for(int h=1;(1<<h)<=n;h++){
  40. //suanqianhouzhui
  41. memset(pre[0],0,sizeof pre[0]);
  42. pre[0][0]=1;
  43. for(int i=0;i<G[u].size();i++){
  44. int v=G[u][i];if(v==p){memcpy(pre[i+1],pre[i],sizeof pre[i]);continue;}
  45. memset(pre[i+1],0,sizeof pre[i+1]);
  46. for(int j=0;j<=K;j++){
  47. up(pre[i+1][j],pre[i][j]);
  48. if(j<K)up(pre[i+1][j+1],1LL*dp1[h-1][v]*pre[i][j]%mod);
  49. }
  50. }
  51. int lst=G[u].size();
  52. memset(suf[lst],0,sizeof suf[lst]);
  53. suf[lst][1]=dp2[h-1][u];
  54. suf[lst][0]=1;
  55. for(int i=G[u].size()-1;i>=0;i--){
  56. int v=G[u][i];if(v==p){memcpy(suf[i],suf[i+1],sizeof suf[i+1]);continue;}
  57. memset(suf[i],0,sizeof suf[i]);
  58. for(int j=0;j<=K;j++){
  59. up(suf[i][j],suf[i+1][j]);
  60. if(j<K)up(suf[i][j+1],1LL*dp1[h-1][v]*suf[i+1][j]%mod);
  61. }
  62. /*
  63. if(h==2&&u==2){
  64. printf("v=%d\n",v);
  65. for(int j=0;j<=K;j++)printf("",suf);
  66. }
  67. */
  68. }
  69. /*
  70. if(u==2){
  71. puts("haha");
  72. for(int i=0;i<=G[u].size();i++){
  73. for(int j=0;j<=K;j++)printf("%d ",suf[i][j]);puts("");
  74. }
  75. }
  76. */
  77. for(int i=0;i<G[u].size();i++){
  78. int v=G[u][i];if(v==p)continue;
  79. dp2[h][v]=0;
  80. for(int j=0;j<=K;j++){
  81. up(dp2[h][v],1LL*pre[i][j]*suf[i+1][K-j]%mod);
  82. }
  83. }
  84. /*
  85. if(suf[0][K]){
  86. printf("u=%d h=%d suf=%d\n",u,h,suf[0][K]);
  87. }
  88. */
  89. up(ans,suf[0][K]);
  90. }
  91. for(int i=0;i<G[u].size();i++){
  92. int v=G[u][i];if(v==p)continue;
  93. dp2[0][v]=1;
  94. dfs2(v,u);
  95. }
  96.  
  97. }
  98. void solve () {
  99. for(int i=1;i<=n;i++)G[i].clear();
  100. for(int i=1;i<n;i++){
  101. int u,v;scanf("%d%d",&u,&v);
  102. G[u].push_back(v);
  103. G[v].push_back(u);
  104. }
  105. ans=n;
  106. dfs1(1,0);
  107. dfs2(1,0);
  108. printf("%d\n",ans);
  109. }
  110.  
  111. int main () {
  112. while ( ~scanf ( "%d%d" , &n,&K ) ) solve () ;
  113. return 0 ;
  114. }

  

F. Playing with Numbers

枚举答案中2和3的幂次来自哪里即可。

  1. #include <bits/stdc++.h>
  2. using namespace std ;
  3.  
  4. const int MAXN = 50005 ;
  5.  
  6. int a[MAXN] , b[MAXN] ;
  7. int prea[MAXN][2] , preb[MAXN][2] ;
  8. int sufa[MAXN][2] , sufb[MAXN][2] ;
  9. int n ;
  10.  
  11. double getlog ( int x , int y ) {
  12. return x * log ( 2.0 ) + y * log ( 3.0 ) ;
  13. }
  14.  
  15. void getlcm () {
  16. int ansa = 0 , ansb = 0 ;
  17. for ( int i = 1 ; i <= n ; ++ i ) {
  18. int tmpa = min ( prea[i - 1][1] , sufa[i + 1][1] ) ;
  19. int tmpb = min ( preb[i - 1][1] , sufb[i + 1][1] ) ;
  20. tmpa = max ( tmpa , a[i] ) ;
  21. tmpb = max ( tmpb , b[i] ) ;
  22. if ( getlog ( tmpa , tmpb ) > getlog ( ansa , ansb ) ) {
  23. ansa = tmpa ;
  24. ansb = tmpb ;
  25. }
  26. }
  27. printf ( "%d %d" , ansa , ansb ) ;
  28. }
  29.  
  30. void getgcd () {
  31. int ansa = 1000 , ansb = 1000 ;
  32. for ( int i = 1 ; i <= n ; ++ i ) {
  33. int tmpa = max ( prea[i - 1][0] , sufa[i + 1][0] ) ;
  34. int tmpb = max ( preb[i - 1][0] , sufb[i + 1][0] ) ;
  35. tmpa = min ( tmpa , a[i] ) ;
  36. tmpb = min ( tmpb , b[i] ) ;
  37. if ( getlog ( tmpa , tmpb ) < getlog ( ansa , ansb ) ) {
  38. ansa = tmpa ;
  39. ansb = tmpb ;
  40. }
  41. }
  42. printf ( "%d %d" , ansa , ansb ) ;
  43. }
  44.  
  45. void solve () {
  46. for ( int i = 1 ; i <= n ; ++ i ) {
  47. scanf ( "%d%d" , &a[i] , &b[i] ) ;
  48. }
  49. if ( n == 1 ) {
  50. printf ( "%d %d %d %d\n" , a[1] , b[1] , a[1] , b[1] ) ;
  51. return ;
  52. }
  53. if ( n == 2 ) {
  54. if ( a[1] < a[2] ) swap ( a[1] , a[2] ) ;
  55. if ( b[1] < b[2] ) swap ( b[1] , b[2] ) ;
  56. printf ( "%d %d %d %d\n" , a[1] , b[1] , a[1] , b[1] ) ;
  57. printf ( "%d %d %d %d\n" , a[2] , b[2] , a[2] , b[2] ) ;
  58. return ;
  59. }
  60. prea[0][0] = preb[0][0] = 0 ;
  61. prea[0][1] = preb[0][1] = 1000 ;
  62. sufa[n + 1][0] = sufb[n + 1][0] = 0 ;
  63. sufa[n + 1][1] = sufb[n + 1][1] = 1000 ;
  64. for ( int i = 1 ; i <= n ; ++ i ) {
  65. prea[i][0] = max ( prea[i - 1][0] , a[i] ) ;
  66. preb[i][0] = max ( preb[i - 1][0] , b[i] ) ;
  67. prea[i][1] = min ( prea[i - 1][1] , a[i] ) ;
  68. preb[i][1] = min ( preb[i - 1][1] , b[i] ) ;
  69. }
  70. for ( int i = n ; i >= 1 ; -- i ) {
  71. sufa[i][0] = max ( sufa[i + 1][0] , a[i] ) ;
  72. sufb[i][0] = max ( sufb[i + 1][0] , b[i] ) ;
  73. sufa[i][1] = min ( sufa[i + 1][1] , a[i] ) ;
  74. sufb[i][1] = min ( sufb[i + 1][1] , b[i] ) ;
  75. }
  76. for ( int i = 0 ; i < n ; ++ i ) {
  77. if ( i <= n - 3 ) {
  78. printf ( "%d %d" , prea[n][0] , preb[n][0] ) ;
  79. } else if ( i == n - 2 ) {
  80. getlcm () ;
  81. } else {
  82. printf ( "%d %d" , prea[n][1] , preb[n][1] ) ;
  83. }
  84. printf ( " " ) ;
  85. if ( i == 0 ) {
  86. printf ( "%d %d" , prea[n][0] , preb[n][0] ) ;
  87. } else if ( i == 1 ) {
  88. getgcd () ;
  89. } else {
  90. printf ( "%d %d" , prea[n][1] , preb[n][1] ) ;
  91. }
  92. puts ( "" ) ;
  93. }
  94. }
  95.  
  96. int main () {
  97. while ( ~scanf ( "%d" , &n ) ) solve () ;
  98. return 0 ;
  99. }

  

G. Scaffolding

留坑。

H. Slim Cut

枚举割中最大的边,那么大于它的边都要保留,得到若干个连通块,那么需要把这些连通块划分给$S$或者$T$,使得点数尽量均衡,01背包即可。

用并查集维护连通块,那么就变成了带增删物品的01背包,在线段树上分治同时用bitset加速即可。

时间复杂度$O(\frac{n^2\log n}{64})$。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<bitset>
  5. using namespace std;
  6. const int N=50010,M=140000,MAXE=3000000;
  7. typedef bitset<7010>BS;
  8. int n,m,i,j,x,y,f[N],size[N],id[N];
  9. int pos,st[N],en[N],val[N],cnt;
  10. double ans=1e9;
  11. int gq[M],g[M],v[MAXE],nxt[MAXE],ed;
  12. BS base;
  13. struct E{
  14. int x,y,w;
  15. }e[N];
  16. inline bool cmp(const E&a,const E&b){return a.w>b.w;}
  17. int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
  18. inline void add(int&x,int y){
  19. v[++ed]=y;
  20. nxt[ed]=x;
  21. x=ed;
  22. }
  23. inline void addquery(int x){
  24. add(gq[pos],x);
  25. }
  26. inline void merge(int x,int y){
  27. x=F(x);
  28. y=F(y);
  29. if(x==y)return;
  30. en[id[x]]=pos;
  31. en[id[y]]=pos;
  32. pos++;
  33. cnt++;
  34. st[cnt]=pos;
  35. val[cnt]=size[x]+size[y];
  36. size[y]+=size[x];
  37. f[x]=y;
  38. id[y]=cnt;
  39. }
  40. void change(int x,int a,int b,int c,int d,int p){
  41. if(c<=a&&b<=d){
  42. add(g[x],p);
  43. return;
  44. }
  45. int mid=(a+b)>>1;
  46. if(c<=mid)change(x<<1,a,mid,c,d,p);
  47. if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
  48. }
  49. void dfs(int x,int a,int b,BS dp,int cur){
  50. for(int i=g[x];i;i=nxt[i])dp|=dp<<v[i],cur+=v[i];
  51. if(a==b){
  52. if(cur!=n)while(1);
  53. int now=-1;
  54. for(int i=n/2;i>=1;i--)if(dp[i]){
  55. now=i;
  56. break;
  57. }
  58. if(now<1)return;
  59. for(int i=gq[a];i;i=nxt[i]){
  60. ans=min(ans,1.0*v[i]/now);
  61. }
  62. return;
  63. }
  64. int mid=(a+b)>>1;
  65. dfs(x<<1,a,mid,dp,cur);
  66. dfs(x<<1|1,mid+1,b,dp,cur);
  67. }
  68. int main(){
  69. scanf("%d%d",&n,&m);
  70. for(i=1;i<=m;i++){
  71. scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
  72. e[i].x++;e[i].y++;
  73. }
  74. sort(e+1,e+m+1,cmp);
  75. for(i=1;i<=n;i++){
  76. f[i]=i;size[i]=1;
  77. id[i]=++cnt;
  78. val[i]=1;
  79. st[i]=1;
  80. }
  81. pos=1;
  82. for(i=1;i<=m;i=j){
  83. addquery(e[i].w);
  84. for(j=i;j<=m&&e[i].w==e[j].w;j++){
  85. merge(e[j].x,e[j].y);
  86. }
  87. }
  88. for(i=1;i<=cnt;i++)if(!en[i])en[i]=pos;
  89. for(i=1;i<=cnt;i++)change(1,1,pos,st[i],en[i],val[i]);
  90. base[0]=1;
  91. dfs(1,1,pos,base,0);
  92. printf("%.10f",ans);
  93. }

  

I. Special Tour

留坑。

J. Taboo

建立AC自动机,然后DP即可,发现环就返回无限解。

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cmath>
  4. #include<cstring>
  5. #include<algorithm>
  6. using namespace std;
  7. const int N=200010;
  8. const int inf=100000000;
  9. int n,i,j,x;
  10. char s[N];
  11. int tot,son[N][2],ban[N],fail[N],q[N];
  12. int f[N],vis[N],in[N];
  13. void ins(){
  14. scanf("%s",s);
  15. int l=strlen(s);
  16. int i,x=0,w;
  17. for(i=0;i<l;i++){
  18. w=s[i]-'0';
  19. if(!son[x][w])son[x][w]=++tot;
  20. x=son[x][w];
  21. }
  22. ban[x]=1;
  23. }
  24. void make(){
  25. int h=1,t=0,i,j,x;
  26. fail[0]=-1;
  27. for(i=0;i<2;i++)if(son[0][i])q[++t]=son[0][i];
  28. while(h<=t){
  29. for(x=q[h++],i=0;i<2;i++)
  30. if(son[x][i]){
  31. fail[son[x][i]]=son[fail[x]][i];
  32. q[++t]=son[x][i];
  33. ban[son[x][i]]|=ban[fail[son[x][i]]];
  34. }else{
  35. son[x][i]=son[fail[x]][i];
  36. }
  37. }
  38. }
  39. int dp(int x){
  40. if(in[x]){
  41. puts("-1");
  42. exit(0);
  43. }
  44. if(vis[x])return f[x];
  45. in[x]=1;
  46. vis[x]=1;
  47. f[x]=-inf;
  48. if(!ban[x]){
  49. f[x]=0;
  50. for(int i=0;i<2;i++){
  51. f[x]=max(f[x],dp(son[x][i])+1);
  52. }
  53. }
  54. in[x]=0;
  55. // printf("dp[%d]=%d\n",x,f[x]);
  56. return f[x];
  57. }
  58. int main(){
  59. scanf("%d",&n);
  60. while(n--)ins();
  61. make();
  62. dp(0);
  63. //printf("ans=%d\n",f[0]);
  64. for(x=0,i=1;i<=f[0];i++){
  65. for(int j=0;j<2;j++){
  66. if(f[son[x][j]]+1==f[x]){
  67. x=son[x][j];
  68. printf("%d",j);
  69. break;
  70. }
  71. }
  72. }
  73. puts("");
  74. return 0;
  75. }

  

K. Team Up

将包含关系建树,同时将技能按dfs序重标号,那么每门课程都是一个区间。

考虑贪心,每次取出包含这个点的最小的区间即可。

用并查集维护每个点向上第一个还可以选人的节点即可。

  1. #include<cstdio>
  2. #include<cstdlib>
  3. #include<cmath>
  4. #include<vector>
  5. #include<cstring>
  6. #include<algorithm>
  7. using namespace std;
  8. const int N=1500010;
  9. const int inf=100000000;
  10. int n,m,p,i,j,x,size[N],g[N],G[N],v[N],nxt[N],ed,a[N],son[N];
  11. int from[N],father[N];
  12. int st[N],en[N],dfn;
  13. int ans;
  14. int cnt;
  15. int f[N];
  16. bool vis[N];
  17. vector<int>fin[300010];
  18. inline bool cmp(int x,int y){return size[x]>size[y];}//
  19. inline void add(int&x,int y){v[++ed]=y;nxt[ed]=x;x=ed;}//
  20. void dfs(int x){//
  21. for(int i=son[x];i;i=nxt[i])dfs(v[i]);//
  22. for(int i=g[x];i;i=nxt[i]){//
  23. // printf("dfn %d\n",v[i]);
  24. if(!vis[v[i]]){
  25. from[++dfn]=x;//
  26. vis[v[i]]=1;
  27. }
  28. }//
  29. en[x]=dfn;//
  30. }//
  31. int ask(int x){//
  32. if(!x)return 0;//
  33. if(f[x]==x){//
  34. if(G[x])return x;//
  35. f[x]=father[x];//
  36. }//
  37. return f[x]=ask(f[x]);//
  38. }//
  39. void solve(){//
  40. while(1){//
  41. int now=1;//
  42. while(1){//
  43. //printf("->%d %d\n",now,from[now]);
  44. x=ask(from[now]);//return a class
  45. if(!x)return;//
  46. //if(!G[x])while(1);
  47. int y=v[G[x]];//
  48. G[x]=nxt[G[x]];//
  49. fin[ans+1].push_back(y);//
  50. now=en[x]+1;//
  51. if(now>n)break;//
  52. }
  53. ans++;
  54. }
  55. }
  56. int main(){
  57. scanf("%d%d%d",&n,&m,&p);//
  58. for(i=1;i<=m;i++){//
  59. scanf("%d",&size[i]);//
  60. for(j=0;j<size[i];j++){//
  61. scanf("%d",&x);//
  62. add(g[i],x);//
  63. }//
  64. }//50W
  65. for(i=1;i<=p;i++){//
  66. scanf("%d",&x);//
  67. add(G[x],i);//
  68. }//30W
  69. for(i=1;i<=m;i++)a[i]=i;//
  70. sort(a+1,a+m+1,cmp);//
  71. for(i=1;i<=m;i++){//
  72. x=a[i];//
  73. father[x]=from[v[g[x]]];//
  74. for(j=g[x];j;j=nxt[j]){//
  75. from[v[j]]=x;//
  76. }//
  77. }//
  78. for(i=1;i<=n;i++)if(!from[i])return puts("0"),0;//
  79. for(i=1;i<=m;i++)if(father[i])add(son[father[i]],i);//30W
  80. for(i=1;i<=m;i++)if(!father[i])dfs(i);//
  81. //if(dfn<n)while(1);
  82. for(i=1;i<=m;i++)f[i]=i;//
  83. //for(i=1;i<=m;i++)printf("%d\n",father[i]);
  84. solve();//
  85. printf("%d\n",ans);//
  86. for(i=1;i<=ans;i++){//
  87. int t=fin[i].size();//
  88. printf("%d",t);//
  89. for(int j=0;j<t;j++)printf(" %d",fin[i][j]);//
  90. puts("");//
  91. }//
  92. return 0;//
  93. }//

  

Asia Hong Kong Regional Contest 2016的更多相关文章

  1. 2019-2020 ICPC Asia Hong Kong Regional Contest

    题解: https://files.cnblogs.com/files/clrs97/19HKEditorial-V1.zip Code:(Part) A. Axis of Symmetry #inc ...

  2. Asia Hong Kong Regional Contest 2019

    A. Axis of Symmetry B. Binary Tree n 的奇偶性决定胜负. C. Constructing Ranches 路径上点权之和大于,极大值两倍,这是路径上点能拼出多边形的 ...

  3. 2019-2020 ICPC Asia Hong Kong Regional Contest J. Junior Mathematician 题解(数位dp)

    题目链接 题目大意 要你在[l,r]中找到有多少个数满足\(x\equiv f(x)(mod\; m)\) \(f(x)=\sum_{i=1}^{k-1} \sum_{j=i+1}^{k}d(x,i) ...

  4. Hong Kong Regional Online Preliminary 2016 C. Classrooms

    Classrooms 传送门 The new semester is about to begin, and finding classrooms for orientation activities ...

  5. [bfs,深度记录] East Central North America Regional Contest 2016 (ECNA 2016) D Lost in Translation

    Problem D Lost in Translation The word is out that you’ve just finished writing a book entitled How ...

  6. Northwestern European Regional Contest 2016 NWERC ,F题Free Weights(优先队列+Map标记+模拟)

    传送门: Vjudge:https://vjudge.net/problem/Gym-101170F CF: http://codeforces.com/gym/101170 The city of ...

  7. 回文自动机 + DFS --- The 2014 ACM-ICPC Asia Xi’an Regional Contest Problem G.The Problem to Slow Down You

    The Problem to Slow Down You Problem's Link: http://acm.hust.edu.cn/vjudge/problem/viewProblem.actio ...

  8. 2013 Asia acm Hangzhou Regional Contest 杭州现场赛

     B Stealing Harry Potter's Precious 题目大意:给定一个n*m的地图,某些点可以走,某些点可以走某些点不可以走,给定一个起点,又给出了k个点k<=4,要求从起点 ...

  9. 【GYM102091】2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest

    A-Evolution Game 题目大意:有$n$个不同的野兽,定义第$i$ 个野兽有 $i$ 个眼睛和 $h[i]$ 个角,你可以任意从中选择一个野兽进行进化,每次进化角数量必须增加,而且进化后要 ...

随机推荐

  1. VSTO开发之一

    VSTO是微软推出一种对Office产品进行操作的技术,其中提供了一些类库来让开发人员可以更方便地开发出Office的解决方案,即对Word/Excel/Outlook实现一些扩展功能. 新建-> ...

  2. 求两圆相交部分面积(C++)

    已知两圆圆心坐标和半径,求相交部分面积: #include <iostream> using namespace std; #include<cmath> #include&l ...

  3. react+redux官方实例TODO从最简单的入门(2)-- 增

    虽然官网的TodoList的例子写的很详细,但是都是一步到位,就是给你一个action,好家伙,全部都写好了,给你一个reducer,所有功能也是都写好了,但是我们这些小白怎么可能一下就消化那么多,那 ...

  4. sed命令详解

    搜索 纠正错误  添加实例 sed 功能强大的流式文本编辑器 补充说明 sed 是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时 ...

  5. 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】

      [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...

  6. Oracle:试图访问正在使用的事务临时表

    处理步骤为 1.找到表ID select * from dba_objects where object_name like 'TPT_RPWORPA1_QRY' 2.通过表ID查找正在使用的事务 s ...

  7. docker笔记

    安装...不说了 docker info 查看信息 docker pull ...拉取镜像 docker run -it [镜像名] 运行 docker ps查看当前运行的容器  docker ps ...

  8. Python读写csv

    读取csv: http://blog.csdn.net/lixiang0522/article/details/7755059 读取Excel: http://www.cnblogs.com/lhj5 ...

  9. 如何设置redis中hash的field的expire ?

    redis > hset expire:me name tom (integer) redis > hget expire:me name "tom" redis &g ...

  10. DIV+CSS布局

    宽度自适应两列布局 <!DOCTYPE html> <html> <head> <meta charset="gbk"> <t ...