Asia Hong Kong Regional Contest 2016
A. Colourful Graph
可以在$2n$步之内实现交换任意两个点的颜色,然后就可以构造出方案。
- #include <bits/stdc++.h>
- using namespace std ;
- typedef long long LL;
- const int mod=1e9+7,Maxn=222;
- const LL Inf=1LL<<60;
- int n,m,K;
- int col[Maxn],col2[Maxn];
- int done[Maxn],pre[Maxn];
- vector<int>G[Maxn];
- vector<int> way[102][102];//i->j
- int fst[222];
- void bfs(int st){
- for(int i=1;i<=n;i++)done[i]=i==st?1:0;
- queue<int>q;
- q.push(st);
- while(!q.empty()){
- int u=q.front();q.pop();
- for(int i=0;i<G[u].size();i++){
- int v=G[u][i];if(done[v])continue;
- done[v]=1;
- pre[v]=u;
- q.push(v);
- }
- }
- for(int i=1;i<=n;i++){
- int u=i;
- way[st][i].clear();
- for(;u!=st;u=pre[u])way[st][i].push_back(u);
- way[st][i].push_back(st);
- reverse(way[st][i].begin(),way[st][i].end());
- }
- }
- void pt(){
- for(int i=1;i<=n;i++)printf("%d%c",col[i],i==n?'\n':' ');
- }
- void swp(int st,int ed,int ty){
- vector<int>tmp=way[st][ed];
- for(int i=0;i<tmp.size()-1;i++){
- if(i==tmp.size()-2){
- if(ty)col[tmp[i+1]]=col[tmp[i]];
- else swap(col[tmp[i+1]],col[tmp[i]]);
- }
- else swap(col[tmp[i]],col[tmp[i+1]]);
- pt();
- }
- for(int i=tmp.size()-2;i>0;i--){
- swap(col[tmp[i]],col[tmp[i-1]]);
- pt();
- }
- }
- void solve () {
- for(int i=1;i<=n;i++)scanf("%d",col+i),G[i].clear();
- for(int i=1;i<=n;i++)scanf("%d",col2+i);
- for(int i=0;i<m;i++){
- int u,v;scanf("%d%d",&u,&v);
- G[u].push_back(v);
- G[v].push_back(u);
- }
- //puts("ok");
- bool flag=1;
- for(int i=1;i<=n;i++){
- int t=0;
- for(int j=1;j<=n;j++)if(col2[i]==col[j]){t=1;break;}
- if(!t){flag=0;break;}
- }
- if(!flag){
- puts("Impossible");
- return;
- }
- pt();
- for(int i=1;i<=n;i++)bfs(i);
- memset(fst,0,sizeof fst);
- for(int i=1;i<=n;i++){
- if(!fst[col2[i]]){
- fst[col2[i]]=i;
- if(col[i]==col2[i])continue;
- for(int j=1;j<=n;j++){
- if(col[j]==col2[i]){
- swp(j,i,0);
- break;
- }
- }
- }
- }
- for(int i=1;i<=n;i++){
- if(col[i]!=col2[i])swp(fst[col2[i]],i,1);
- }
- }
- int main () {
- while ( ~scanf ( "%d%d%d" , &n,&m,&K ) ) solve () ;
- return 0 ;
- }
B. Doors
答案就是这些折线之间距离的最小值除以2。
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- using namespace std;
- double R,L,W,Alpha,Beta;
- int Case;
- const double pi=acos(-1.0),eps=1e-9,inf=10000.0;
- int sgn(double x){
- if(x<-eps)return -1;
- if(x>eps)return 1;
- return 0;
- }
- struct P{
- double x,y;
- P(){x=y=0;}
- P(double _x,double _y){x=_x,y=_y;}
- P operator+(P v){return P(x+v.x,y+v.y);}
- P operator-(P v){return P(x-v.x,y-v.y);}
- double operator*(P v){return x*v.x+y*v.y;}
- double len(){return hypot(x,y);}
- };
- double cross(P a,P b){return a.x*b.y-a.y*b.x;}
- double dist_point_to_segment(P p,P a,P b){
- if(sgn((p-a)*(b-a))>=0&&sgn((p-b)*(a-b))>=0)
- return fabs(cross(p-a,b-a))/(b-a).len();
- return min((p-a).len(),(p-b).len());
- }
- double cal(P a,P b,P c,P d){
- return min(min(dist_point_to_segment(a,c,d),
- dist_point_to_segment(b,c,d)),
- min(dist_point_to_segment(c,a,b),
- dist_point_to_segment(d,a,b)));
- }
- double solve(){
- P A(-inf,W),B(0,W);
- P D(L,W),E(inf,W);
- P G(L,0),H(inf,0);
- Alpha=pi-Alpha,Beta=pi-Beta;
- P C=D+P(cos(Alpha)*L,sin(Alpha)*L);
- P F=G+P(cos(Beta)*L,sin(Beta)*L);
- double ans=min(L,W);
- ans=min(ans,cal(A,B,C,D));
- ans=min(ans,cal(C,D,F,G));
- ans=min(ans,cal(D,E,F,G));
- ans/=2.0;
- ans=min(ans,R);
- ans=max(ans,0.0);
- return ans;
- }
- int main(){
- scanf("%lf%lf%lf",&R,&L,&W);
- scanf("%d",&Case);
- while(Case--){
- scanf("%lf%lf",&Alpha,&Beta);
- printf("%.9f\n",solve());
- }
- return 0;
- }
C. Peak Tower
求出所有线段相交的时刻,在相邻时刻里三分答案即可。时间复杂度$O(n^4\log n)$。
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<vector>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int N=2000;
- const double eps=1e-9;
- double W,H,E,ans=1e9;
- int n,i,j;
- struct Rec{
- double w,h,sx,sy,vx,vy;
- void read(){
- scanf("%lf%lf%lf%lf%lf%lf",&w,&h,&sx,&sy,&vx,&vy);
- }
- }a[N];
- int sgn(double x){
- if(x<-eps)return -1;
- if(x>eps)return 1;
- return 0;
- }
- int m,cnt;
- double vipy[N];
- int cov[N];
- double ct[1000000];
- int cntt;
- struct Ev{
- double x,l,r;int p;
- Ev(){}
- Ev(double _x,double _l,double _r,int _p){x=_x,l=_l,r=_r,p=_p;}
- }e[N];
- inline bool cmp(const Ev&a,const Ev&b){
- return a.x<b.x;
- }
- double cal(double Time){
- //if(Time<-eps||Time>E+eps)return;
- int i,j;
- m=0;
- for(i=1;i<=n;i++){
- double xl=a[i].sx+a[i].vx*Time,
- xr=xl+a[i].w,
- yl=a[i].sy+a[i].vy*Time,
- yr=yl+a[i].h;
- xl=min(max(xl,0.0),W);
- xr=min(max(xr,0.0),W);
- yl=min(max(yl,0.0),H);
- yr=min(max(yr,0.0),H);
- //printf("%.8f %.8f %.8f %.8f\n",xl,xr,yl,yr);
- if(xl+eps>xr||yl+eps>yr)continue;
- vipy[++m]=yl;
- e[m]=Ev(xl,yl,yr,1);
- vipy[++m]=yr;
- e[m]=Ev(xr,yl,yr,-1);
- }
- double ret=0;
- if(!m){
- //printf("fuck %.8f %.8f\n",Time,0.0);
- ans=0;
- return 0;
- }
- sort(vipy+1,vipy+m+1);
- sort(e+1,e+m+1,cmp);
- for(i=1;i<m;i++)cov[i]=0;
- for(i=1;i<=m;i++){
- if(i>1){
- for(j=1;j<m;j++){
- if(cov[j]>0)ret+=(vipy[j+1]-vipy[j])*(e[i].x-e[i-1].x);
- }
- }
- if(ret>ans)return ret;
- double l=e[i].l,r=e[i].r;
- //printf("ev %.8f %.8f %.8f %d\n",e[i].x,l,r,e[i].p);
- for(j=1;j<m;j++){
- double A=vipy[j],B=vipy[j+1];
- if(sgn(A-l)>=0&&sgn(B-r)<=0){
- cov[j]+=e[i].p;
- }
- }
- }
- //printf("%.8f %.8f\n",Time,ret);
- ans=min(ans,ret);
- return ret;
- }
- inline bool check(double Time){
- if(Time<-eps||Time>E+eps)return 0;
- return 1;
- }
- void deal(double A,double B,double C,double D){
- A-=C;
- B-=D;
- A=-A;
- if(!sgn(B))return;
- if(check(A/B))ct[++cntt]=A/B;
- }
- void search(double l,double r){
- cal(r);
- double m1,m2,s1,s2;
- int step=0;
- while(l+1e-5<r&&step++<10){
- m1=l+(r-l)/3.0;
- m2=r-(r-l)/3.0;
- s1=cal(m1);
- s2=cal(m2);
- if(s1<s2)r=m2-eps;else l=m1+eps;
- }
- }
- int main(){
- scanf("%d%lf%lf%lf",&n,&W,&H,&E);
- for(i=1;i<=n;i++)a[i].read();
- ct[++cntt]=0;
- ct[++cntt]=E;
- a[n+1].w=W;
- a[n+1].h=H;
- for(i=1;i<=n+1;i++)
- for(j=i+1;j<=n+1;j++){
- deal(a[i].sx ,a[i].vx,a[j].sx ,a[j].vx);
- deal(a[i].sx+a[i].w,a[i].vx,a[j].sx ,a[j].vx);
- deal(a[i].sx ,a[i].vx,a[j].sx+a[j].w,a[j].vx);
- deal(a[i].sx+a[i].w,a[i].vx,a[j].sx+a[j].w,a[j].vx);
- deal(a[i].sy ,a[i].vy,a[j].sy ,a[j].vy);
- deal(a[i].sy+a[i].h,a[i].vy,a[j].sy ,a[j].vy);
- deal(a[i].sy ,a[i].vy,a[j].sy+a[j].h,a[j].vy);
- deal(a[i].sy+a[i].h,a[i].vy,a[j].sy+a[j].h,a[j].vy);
- }
- //cal(5);
- sort(ct+1,ct+cntt+1);
- cal(0);
- for(i=1;i<=cntt;i++)if(ct[i]>ct[i-1]+eps){
- search(ct[i-1],ct[i]);
- }
- printf("%.10f",ans);
- }
D. Peak Tram
每个位置最多$O(n^2)$种可能的高度,然后DP即可。
- #include <bits/stdc++.h>
- using namespace std ;
- typedef long long LL;
- const int mod=1e9+7,Maxn=71;
- const LL Inf=1LL<<60;
- vector<LL>V;
- LL p[Maxn],c[Maxn];
- LL dp[2][142*71][71];
- LL pre[2][142*71][71];
- int getid(LL x){
- return lower_bound(V.begin(),V.end(),x)-V.begin();
- }
- int n,K;
- int tot;
- void init(int cs){
- for(int i=0;i<tot;i++){
- for(int j=0;j<=K;j++)dp[cs][i][j]=Inf;
- }
- }
- void calpre(int cs){
- for(int i=0;i<tot;i++){
- for(int j=0;j<=K;j++){
- pre[cs][i][j]=dp[cs][i][j];
- if(i)pre[cs][i][j]=min(pre[cs][i-1][j],pre[cs][i][j]);
- }
- }
- }
- inline void up(LL &x,LL y){if(x>y)x=y;}
- void solve () {
- V.clear();
- LL tp=0;
- V.push_back(tp);
- for(int i=1;i<=n;i++){
- scanf("%lld%lld",p+i,c+i);
- for(int j=-n;j<=n;j++)if(p[i]+j>0)V.push_back(p[i]+j);
- }
- sort(V.begin(),V.end());
- V.erase(unique(V.begin(),V.end()),V.end());
- tot=V.size();
- int cs=0;
- init(cs);
- dp[cs][0][0]=0;
- calpre(cs);
- for(int i=1;i<=n;i++){
- init(cs^1);
- //bubeikanjian
- int tid=getid(p[i]);
- for(int j=1;j<tot;j++){
- LL cost=0;
- if(j<tid){
- cost=abs(V[j]-p[i])*c[i];
- }
- for(int k=0;k<=K;k++){
- up(dp[cs^1][j][k],dp[cs][j][k]+cost);
- }
- }
- //kanjian
- for(int j=1;j<tot;j++){
- LL cost=abs(V[j]-p[i])*c[i];
- for(int k=1;k<=K;k++){
- up(dp[cs^1][j][k],pre[cs][j-1][k-1]+cost);
- up(dp[cs^1][j][k],pre[cs][j-1][k]+cost);
- }
- }
- calpre(cs^1);
- cs^=1;
- }
- LL ans=pre[cs][tot-1][K];
- printf("%lld\n",ans);
- }
- int main () {
- while ( ~scanf ( "%d%d" , &n,&K ) ) solve () ;
- return 0 ;
- }
E. Perfect k-ary Tree
换根树形DP,需要记录树的高度,但是因为是满$k$叉树,因此树高是$O(\log n)$级别的。
- #include <bits/stdc++.h>
- using namespace std ;
- typedef long long LL;
- const int mod=1e9+7,Maxn=100020;
- int dp1[19][Maxn];
- int n,K;
- vector<int>G[Maxn];
- int f[2][6];
- inline void up(int &x,int y){x+=y;if(x>=mod)x-=mod;}
- void dfs1(int u,int p){
- for(int i=0;i<G[u].size();i++){
- int v=G[u][i];if(v==p)continue;
- dfs1(v,u);
- }
- dp1[0][u]=1;
- //printf("u=%d\n",u);
- for(int i=1;(1<<i)<=n;i++){
- int cs=0;
- memset(f[cs],0,sizeof f[cs]);
- f[cs][0]=1;
- for(int j=0;j<G[u].size();j++){
- int v=G[u][j];if(v==p)continue;
- memset(f[cs^1],0,sizeof f[cs^1]);
- for(int k=0;k<=K;k++){
- if(!f[cs][k])continue;
- if(k<K)up(f[cs^1][k+1],1LL*f[cs][k]*dp1[i-1][v]%mod);
- up(f[cs^1][k],f[cs][k]);
- }
- cs^=1;
- }
- dp1[i][u]=f[cs][K];
- }
- //for(int i=0;(1<<i)<=n;i++)printf("%d ",dp1[i][u]);puts("");
- }
- int dp2[19][Maxn];
- int pre[Maxn][6],suf[Maxn][6];
- int ans;
- void dfs2(int u,int p){
- for(int h=1;(1<<h)<=n;h++){
- //suanqianhouzhui
- memset(pre[0],0,sizeof pre[0]);
- pre[0][0]=1;
- for(int i=0;i<G[u].size();i++){
- int v=G[u][i];if(v==p){memcpy(pre[i+1],pre[i],sizeof pre[i]);continue;}
- memset(pre[i+1],0,sizeof pre[i+1]);
- for(int j=0;j<=K;j++){
- up(pre[i+1][j],pre[i][j]);
- if(j<K)up(pre[i+1][j+1],1LL*dp1[h-1][v]*pre[i][j]%mod);
- }
- }
- int lst=G[u].size();
- memset(suf[lst],0,sizeof suf[lst]);
- suf[lst][1]=dp2[h-1][u];
- suf[lst][0]=1;
- for(int i=G[u].size()-1;i>=0;i--){
- int v=G[u][i];if(v==p){memcpy(suf[i],suf[i+1],sizeof suf[i+1]);continue;}
- memset(suf[i],0,sizeof suf[i]);
- for(int j=0;j<=K;j++){
- up(suf[i][j],suf[i+1][j]);
- if(j<K)up(suf[i][j+1],1LL*dp1[h-1][v]*suf[i+1][j]%mod);
- }
- /*
- if(h==2&&u==2){
- printf("v=%d\n",v);
- for(int j=0;j<=K;j++)printf("",suf);
- }
- */
- }
- /*
- if(u==2){
- puts("haha");
- for(int i=0;i<=G[u].size();i++){
- for(int j=0;j<=K;j++)printf("%d ",suf[i][j]);puts("");
- }
- }
- */
- for(int i=0;i<G[u].size();i++){
- int v=G[u][i];if(v==p)continue;
- dp2[h][v]=0;
- for(int j=0;j<=K;j++){
- up(dp2[h][v],1LL*pre[i][j]*suf[i+1][K-j]%mod);
- }
- }
- /*
- if(suf[0][K]){
- printf("u=%d h=%d suf=%d\n",u,h,suf[0][K]);
- }
- */
- up(ans,suf[0][K]);
- }
- for(int i=0;i<G[u].size();i++){
- int v=G[u][i];if(v==p)continue;
- dp2[0][v]=1;
- dfs2(v,u);
- }
- }
- void solve () {
- for(int i=1;i<=n;i++)G[i].clear();
- for(int i=1;i<n;i++){
- int u,v;scanf("%d%d",&u,&v);
- G[u].push_back(v);
- G[v].push_back(u);
- }
- ans=n;
- dfs1(1,0);
- dfs2(1,0);
- printf("%d\n",ans);
- }
- int main () {
- while ( ~scanf ( "%d%d" , &n,&K ) ) solve () ;
- return 0 ;
- }
F. Playing with Numbers
枚举答案中2和3的幂次来自哪里即可。
- #include <bits/stdc++.h>
- using namespace std ;
- const int MAXN = 50005 ;
- int a[MAXN] , b[MAXN] ;
- int prea[MAXN][2] , preb[MAXN][2] ;
- int sufa[MAXN][2] , sufb[MAXN][2] ;
- int n ;
- double getlog ( int x , int y ) {
- return x * log ( 2.0 ) + y * log ( 3.0 ) ;
- }
- void getlcm () {
- int ansa = 0 , ansb = 0 ;
- for ( int i = 1 ; i <= n ; ++ i ) {
- int tmpa = min ( prea[i - 1][1] , sufa[i + 1][1] ) ;
- int tmpb = min ( preb[i - 1][1] , sufb[i + 1][1] ) ;
- tmpa = max ( tmpa , a[i] ) ;
- tmpb = max ( tmpb , b[i] ) ;
- if ( getlog ( tmpa , tmpb ) > getlog ( ansa , ansb ) ) {
- ansa = tmpa ;
- ansb = tmpb ;
- }
- }
- printf ( "%d %d" , ansa , ansb ) ;
- }
- void getgcd () {
- int ansa = 1000 , ansb = 1000 ;
- for ( int i = 1 ; i <= n ; ++ i ) {
- int tmpa = max ( prea[i - 1][0] , sufa[i + 1][0] ) ;
- int tmpb = max ( preb[i - 1][0] , sufb[i + 1][0] ) ;
- tmpa = min ( tmpa , a[i] ) ;
- tmpb = min ( tmpb , b[i] ) ;
- if ( getlog ( tmpa , tmpb ) < getlog ( ansa , ansb ) ) {
- ansa = tmpa ;
- ansb = tmpb ;
- }
- }
- printf ( "%d %d" , ansa , ansb ) ;
- }
- void solve () {
- for ( int i = 1 ; i <= n ; ++ i ) {
- scanf ( "%d%d" , &a[i] , &b[i] ) ;
- }
- if ( n == 1 ) {
- printf ( "%d %d %d %d\n" , a[1] , b[1] , a[1] , b[1] ) ;
- return ;
- }
- if ( n == 2 ) {
- if ( a[1] < a[2] ) swap ( a[1] , a[2] ) ;
- if ( b[1] < b[2] ) swap ( b[1] , b[2] ) ;
- printf ( "%d %d %d %d\n" , a[1] , b[1] , a[1] , b[1] ) ;
- printf ( "%d %d %d %d\n" , a[2] , b[2] , a[2] , b[2] ) ;
- return ;
- }
- prea[0][0] = preb[0][0] = 0 ;
- prea[0][1] = preb[0][1] = 1000 ;
- sufa[n + 1][0] = sufb[n + 1][0] = 0 ;
- sufa[n + 1][1] = sufb[n + 1][1] = 1000 ;
- for ( int i = 1 ; i <= n ; ++ i ) {
- prea[i][0] = max ( prea[i - 1][0] , a[i] ) ;
- preb[i][0] = max ( preb[i - 1][0] , b[i] ) ;
- prea[i][1] = min ( prea[i - 1][1] , a[i] ) ;
- preb[i][1] = min ( preb[i - 1][1] , b[i] ) ;
- }
- for ( int i = n ; i >= 1 ; -- i ) {
- sufa[i][0] = max ( sufa[i + 1][0] , a[i] ) ;
- sufb[i][0] = max ( sufb[i + 1][0] , b[i] ) ;
- sufa[i][1] = min ( sufa[i + 1][1] , a[i] ) ;
- sufb[i][1] = min ( sufb[i + 1][1] , b[i] ) ;
- }
- for ( int i = 0 ; i < n ; ++ i ) {
- if ( i <= n - 3 ) {
- printf ( "%d %d" , prea[n][0] , preb[n][0] ) ;
- } else if ( i == n - 2 ) {
- getlcm () ;
- } else {
- printf ( "%d %d" , prea[n][1] , preb[n][1] ) ;
- }
- printf ( " " ) ;
- if ( i == 0 ) {
- printf ( "%d %d" , prea[n][0] , preb[n][0] ) ;
- } else if ( i == 1 ) {
- getgcd () ;
- } else {
- printf ( "%d %d" , prea[n][1] , preb[n][1] ) ;
- }
- puts ( "" ) ;
- }
- }
- int main () {
- while ( ~scanf ( "%d" , &n ) ) solve () ;
- return 0 ;
- }
G. Scaffolding
留坑。
H. Slim Cut
枚举割中最大的边,那么大于它的边都要保留,得到若干个连通块,那么需要把这些连通块划分给$S$或者$T$,使得点数尽量均衡,01背包即可。
用并查集维护连通块,那么就变成了带增删物品的01背包,在线段树上分治同时用bitset加速即可。
时间复杂度$O(\frac{n^2\log n}{64})$。
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<bitset>
- using namespace std;
- const int N=50010,M=140000,MAXE=3000000;
- typedef bitset<7010>BS;
- int n,m,i,j,x,y,f[N],size[N],id[N];
- int pos,st[N],en[N],val[N],cnt;
- double ans=1e9;
- int gq[M],g[M],v[MAXE],nxt[MAXE],ed;
- BS base;
- struct E{
- int x,y,w;
- }e[N];
- inline bool cmp(const E&a,const E&b){return a.w>b.w;}
- int F(int x){return f[x]==x?x:f[x]=F(f[x]);}
- inline void add(int&x,int y){
- v[++ed]=y;
- nxt[ed]=x;
- x=ed;
- }
- inline void addquery(int x){
- add(gq[pos],x);
- }
- inline void merge(int x,int y){
- x=F(x);
- y=F(y);
- if(x==y)return;
- en[id[x]]=pos;
- en[id[y]]=pos;
- pos++;
- cnt++;
- st[cnt]=pos;
- val[cnt]=size[x]+size[y];
- size[y]+=size[x];
- f[x]=y;
- id[y]=cnt;
- }
- void change(int x,int a,int b,int c,int d,int p){
- if(c<=a&&b<=d){
- add(g[x],p);
- return;
- }
- int mid=(a+b)>>1;
- if(c<=mid)change(x<<1,a,mid,c,d,p);
- if(d>mid)change(x<<1|1,mid+1,b,c,d,p);
- }
- void dfs(int x,int a,int b,BS dp,int cur){
- for(int i=g[x];i;i=nxt[i])dp|=dp<<v[i],cur+=v[i];
- if(a==b){
- if(cur!=n)while(1);
- int now=-1;
- for(int i=n/2;i>=1;i--)if(dp[i]){
- now=i;
- break;
- }
- if(now<1)return;
- for(int i=gq[a];i;i=nxt[i]){
- ans=min(ans,1.0*v[i]/now);
- }
- return;
- }
- int mid=(a+b)>>1;
- dfs(x<<1,a,mid,dp,cur);
- dfs(x<<1|1,mid+1,b,dp,cur);
- }
- int main(){
- scanf("%d%d",&n,&m);
- for(i=1;i<=m;i++){
- scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].w);
- e[i].x++;e[i].y++;
- }
- sort(e+1,e+m+1,cmp);
- for(i=1;i<=n;i++){
- f[i]=i;size[i]=1;
- id[i]=++cnt;
- val[i]=1;
- st[i]=1;
- }
- pos=1;
- for(i=1;i<=m;i=j){
- addquery(e[i].w);
- for(j=i;j<=m&&e[i].w==e[j].w;j++){
- merge(e[j].x,e[j].y);
- }
- }
- for(i=1;i<=cnt;i++)if(!en[i])en[i]=pos;
- for(i=1;i<=cnt;i++)change(1,1,pos,st[i],en[i],val[i]);
- base[0]=1;
- dfs(1,1,pos,base,0);
- printf("%.10f",ans);
- }
I. Special Tour
留坑。
J. Taboo
建立AC自动机,然后DP即可,发现环就返回无限解。
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int N=200010;
- const int inf=100000000;
- int n,i,j,x;
- char s[N];
- int tot,son[N][2],ban[N],fail[N],q[N];
- int f[N],vis[N],in[N];
- void ins(){
- scanf("%s",s);
- int l=strlen(s);
- int i,x=0,w;
- for(i=0;i<l;i++){
- w=s[i]-'0';
- if(!son[x][w])son[x][w]=++tot;
- x=son[x][w];
- }
- ban[x]=1;
- }
- void make(){
- int h=1,t=0,i,j,x;
- fail[0]=-1;
- for(i=0;i<2;i++)if(son[0][i])q[++t]=son[0][i];
- while(h<=t){
- for(x=q[h++],i=0;i<2;i++)
- if(son[x][i]){
- fail[son[x][i]]=son[fail[x]][i];
- q[++t]=son[x][i];
- ban[son[x][i]]|=ban[fail[son[x][i]]];
- }else{
- son[x][i]=son[fail[x]][i];
- }
- }
- }
- int dp(int x){
- if(in[x]){
- puts("-1");
- exit(0);
- }
- if(vis[x])return f[x];
- in[x]=1;
- vis[x]=1;
- f[x]=-inf;
- if(!ban[x]){
- f[x]=0;
- for(int i=0;i<2;i++){
- f[x]=max(f[x],dp(son[x][i])+1);
- }
- }
- in[x]=0;
- // printf("dp[%d]=%d\n",x,f[x]);
- return f[x];
- }
- int main(){
- scanf("%d",&n);
- while(n--)ins();
- make();
- dp(0);
- //printf("ans=%d\n",f[0]);
- for(x=0,i=1;i<=f[0];i++){
- for(int j=0;j<2;j++){
- if(f[son[x][j]]+1==f[x]){
- x=son[x][j];
- printf("%d",j);
- break;
- }
- }
- }
- puts("");
- return 0;
- }
K. Team Up
将包含关系建树,同时将技能按dfs序重标号,那么每门课程都是一个区间。
考虑贪心,每次取出包含这个点的最小的区间即可。
用并查集维护每个点向上第一个还可以选人的节点即可。
- #include<cstdio>
- #include<cstdlib>
- #include<cmath>
- #include<vector>
- #include<cstring>
- #include<algorithm>
- using namespace std;
- const int N=1500010;
- const int inf=100000000;
- int n,m,p,i,j,x,size[N],g[N],G[N],v[N],nxt[N],ed,a[N],son[N];
- int from[N],father[N];
- int st[N],en[N],dfn;
- int ans;
- int cnt;
- int f[N];
- bool vis[N];
- vector<int>fin[300010];
- inline bool cmp(int x,int y){return size[x]>size[y];}//
- inline void add(int&x,int y){v[++ed]=y;nxt[ed]=x;x=ed;}//
- void dfs(int x){//
- for(int i=son[x];i;i=nxt[i])dfs(v[i]);//
- for(int i=g[x];i;i=nxt[i]){//
- // printf("dfn %d\n",v[i]);
- if(!vis[v[i]]){
- from[++dfn]=x;//
- vis[v[i]]=1;
- }
- }//
- en[x]=dfn;//
- }//
- int ask(int x){//
- if(!x)return 0;//
- if(f[x]==x){//
- if(G[x])return x;//
- f[x]=father[x];//
- }//
- return f[x]=ask(f[x]);//
- }//
- void solve(){//
- while(1){//
- int now=1;//
- while(1){//
- //printf("->%d %d\n",now,from[now]);
- x=ask(from[now]);//return a class
- if(!x)return;//
- //if(!G[x])while(1);
- int y=v[G[x]];//
- G[x]=nxt[G[x]];//
- fin[ans+1].push_back(y);//
- now=en[x]+1;//
- if(now>n)break;//
- }
- ans++;
- }
- }
- int main(){
- scanf("%d%d%d",&n,&m,&p);//
- for(i=1;i<=m;i++){//
- scanf("%d",&size[i]);//
- for(j=0;j<size[i];j++){//
- scanf("%d",&x);//
- add(g[i],x);//
- }//
- }//50W
- for(i=1;i<=p;i++){//
- scanf("%d",&x);//
- add(G[x],i);//
- }//30W
- for(i=1;i<=m;i++)a[i]=i;//
- sort(a+1,a+m+1,cmp);//
- for(i=1;i<=m;i++){//
- x=a[i];//
- father[x]=from[v[g[x]]];//
- for(j=g[x];j;j=nxt[j]){//
- from[v[j]]=x;//
- }//
- }//
- for(i=1;i<=n;i++)if(!from[i])return puts("0"),0;//
- for(i=1;i<=m;i++)if(father[i])add(son[father[i]],i);//30W
- for(i=1;i<=m;i++)if(!father[i])dfs(i);//
- //if(dfn<n)while(1);
- for(i=1;i<=m;i++)f[i]=i;//
- //for(i=1;i<=m;i++)printf("%d\n",father[i]);
- solve();//
- printf("%d\n",ans);//
- for(i=1;i<=ans;i++){//
- int t=fin[i].size();//
- printf("%d",t);//
- for(int j=0;j<t;j++)printf(" %d",fin[i][j]);//
- puts("");//
- }//
- return 0;//
- }//
Asia Hong Kong Regional Contest 2016的更多相关文章
- 2019-2020 ICPC Asia Hong Kong Regional Contest
题解: https://files.cnblogs.com/files/clrs97/19HKEditorial-V1.zip Code:(Part) A. Axis of Symmetry #inc ...
- Asia Hong Kong Regional Contest 2019
A. Axis of Symmetry B. Binary Tree n 的奇偶性决定胜负. C. Constructing Ranches 路径上点权之和大于,极大值两倍,这是路径上点能拼出多边形的 ...
- 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) ...
- Hong Kong Regional Online Preliminary 2016 C. Classrooms
Classrooms 传送门 The new semester is about to begin, and finding classrooms for orientation activities ...
- [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 ...
- 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 ...
- 回文自动机 + 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 ...
- 2013 Asia acm Hangzhou Regional Contest 杭州现场赛
B Stealing Harry Potter's Precious 题目大意:给定一个n*m的地图,某些点可以走,某些点可以走某些点不可以走,给定一个起点,又给出了k个点k<=4,要求从起点 ...
- 【GYM102091】2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest
A-Evolution Game 题目大意:有$n$个不同的野兽,定义第$i$ 个野兽有 $i$ 个眼睛和 $h[i]$ 个角,你可以任意从中选择一个野兽进行进化,每次进化角数量必须增加,而且进化后要 ...
随机推荐
- VSTO开发之一
VSTO是微软推出一种对Office产品进行操作的技术,其中提供了一些类库来让开发人员可以更方便地开发出Office的解决方案,即对Word/Excel/Outlook实现一些扩展功能. 新建-> ...
- 求两圆相交部分面积(C++)
已知两圆圆心坐标和半径,求相交部分面积: #include <iostream> using namespace std; #include<cmath> #include&l ...
- react+redux官方实例TODO从最简单的入门(2)-- 增
虽然官网的TodoList的例子写的很详细,但是都是一步到位,就是给你一个action,好家伙,全部都写好了,给你一个reducer,所有功能也是都写好了,但是我们这些小白怎么可能一下就消化那么多,那 ...
- sed命令详解
搜索 纠正错误 添加实例 sed 功能强大的流式文本编辑器 补充说明 sed 是一种流编辑器,它是文本处理中非常中的工具,能够完美的配合正则表达式使用,功能不同凡响.处理时,把当前处理的行存储在临时 ...
- 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】
[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...
- Oracle:试图访问正在使用的事务临时表
处理步骤为 1.找到表ID select * from dba_objects where object_name like 'TPT_RPWORPA1_QRY' 2.通过表ID查找正在使用的事务 s ...
- docker笔记
安装...不说了 docker info 查看信息 docker pull ...拉取镜像 docker run -it [镜像名] 运行 docker ps查看当前运行的容器 docker ps ...
- Python读写csv
读取csv: http://blog.csdn.net/lixiang0522/article/details/7755059 读取Excel: http://www.cnblogs.com/lhj5 ...
- 如何设置redis中hash的field的expire ?
redis > hset expire:me name tom (integer) redis > hget expire:me name "tom" redis &g ...
- DIV+CSS布局
宽度自适应两列布局 <!DOCTYPE html> <html> <head> <meta charset="gbk"> <t ...