XVII Open Cup named after E.V. Pankratiev. GP of Siberia, Division 1

1. Ski race

枚举枚举倍数判断即可。时间复杂度$O(n\log m)$。

#include<cstdio>
#include<algorithm>
using namespace std;
int n,m,i,j,ans,flag,q[111111],a[111111];
bool v[11111111];
int main(){
  freopen("input.txt","r",stdin);
  freopen("output.txt","w",stdout);
  scanf("%d",&n);
  m=10000000;
  for(i=1;i<=n;i++){
    scanf("%d",&a[i]);
    v[a[i]]=1;
  }
  for(i=1;i<=n;i++){
    flag=1;
    for(j=a[i]*2;j<=m;j+=a[i])if(v[j]){
      flag=0;
      break;
    }
    if(flag)q[++ans]=a[i];
  }
  sort(q+1,q+ans+1);
  for(i=1;i<=ans;i++)printf("%d ",q[i]);
}

  

2. Chairs

DP求出每个点开始走最多能碰到几个椅子,时间复杂度$O(nm)$。

#include <bits/stdc++.h>
using namespace std ;

const int MAXN = 105 ;
const int INF = 0x3f3f3f3f ;

int G[MAXN][MAXN] , dp[MAXN][MAXN] , p[MAXN][MAXN] ;
int n , m , k ;

void put ( int x , int y ) {
	if ( x == n && y == m ) return ;
	//printf ( "%d %d\n" , x , y ) ;
	if ( p[x][y] == 0 ) {
		printf ( "D" ) ;
		put ( x + 1 , y ) ;
	} else {
		printf ( "R" ) ;
		put ( x , y + 1 ) ;
	}
}

void solve () {
	memset ( dp , -INF , sizeof dp ) ;
	memset ( G , 0 , sizeof G ) ;
	memset ( p , 0 , sizeof p ) ;
	for ( int i = 0 ; i < k ; ++ i ) {
		int x , y ;
		scanf ( "%d%d" , &x , &y ) ;
		G[x][y] ++ ;
	}
	dp[n][m] = G[n][m] ;
	for ( int i = n ; i >= 1 ; -- i ) {
		for ( int j = m ; j >= 1 ; -- j ) {
			if ( i == n && j == m ) continue ;
			if ( dp[i][j + 1] <= dp[i + 1][j] ) {
				dp[i][j] = dp[i + 1][j] + G[i][j] ;
				p[i][j] = 0 ;
			} else {
				dp[i][j] = dp[i][j + 1] + G[i][j] ;
				p[i][j] = 1 ;
			}
		}
	}
	if ( dp[1][1] != k ) printf ( "Impossible" ) ;
	else put ( 1 , 1 ) ;
	puts ( "" ) ;
}

int main () {
	freopen ( "input.txt" , "r" , stdin ) ;
	freopen ( "output.txt" , "w" , stdout ) ;
	while ( ~scanf ( "%d%d%d" , &n , &m , &k ) ) solve () ;
	return 0 ;
}

  

3. Triangle

留坑。

 

4. Wires

将所有点对$(a,b)$按$a$排序,那么内外都要满足$b$递增。

设$f[i][j][k]$表示考虑前$i$个点,最后一个与$i$不在一个序列的数的$b$是$j$,且$i$属于序列$k$时的最小总代价。

那么状态的保存以及转移均可以用线段树实现,时间复杂度$O(n\log n)$。

#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=100010,M=262150;
const double inf=1e30;
int A,B,n,i,b[N];
double v0[N],v1[N];
struct P{int l,r;}a[N];
inline bool cmp(const P&a,const P&b){return a.l<b.l;}
inline int lower(int x){
  int l=1,r=n,mid,t;
  while(l<=r)if(b[mid=(l+r)>>1]<=x)l=(t=mid)+1;else r=mid-1;
  return t;
}
struct DS{
double v[M],ta[M],tc[M];
void build(int x,int a,int b){
  v[x]=inf;
  tc[x]=-9;
  if(a==b)return;
  int mid=(a+b)>>1;
  build(x<<1,a,mid);
  build(x<<1|1,mid+1,b);
}
inline void add1(int x,double p){
  v[x]+=p;
  if(tc[x]>-1)tc[x]+=p;else ta[x]+=p;
}
inline void col1(int x,double p){
  v[x]=p;
  tc[x]=p;
  ta[x]=0;
}
inline void pb(int x){
  if(ta[x]>0.5){
    add1(x<<1,ta[x]);
    add1(x<<1|1,ta[x]);
    ta[x]=0;
  }
  if(tc[x]>-1){
    col1(x<<1,tc[x]);
    col1(x<<1|1,tc[x]);
    tc[x]=-9;
  }
}
inline void up(int x){
  v[x]=min(v[x<<1],v[x<<1|1]);
}
void change(int x,int a,int b,int c,double p){
  if(a==b){
    v[x]=min(v[x],p);
    return;
  }
  pb(x);
  int mid=(a+b)>>1;
  if(c<=mid)change(x<<1,a,mid,c,p);
  else change(x<<1|1,mid+1,b,c,p);
  up(x);
}
double ask(int x,int a,int b,int c,int d){
  if(c<=a&&b<=d)return v[x];
  pb(x);
  int mid=(a+b)>>1;
  double t=inf;
  if(c<=mid)t=ask(x<<1,a,mid,c,d);
  if(d>mid)t=min(t,ask(x<<1|1,mid+1,b,c,d));
  return t;
}
}f,g;
int main(){
  freopen("input.txt","r",stdin);
  freopen("output.txt","w",stdout);
  scanf("%d%d%d",&A,&B,&n);
  for(i=1;i<=n;i++)scanf("%d",&a[i].l);
  for(i=1;i<=n;i++)scanf("%d",&a[i].r),b[i]=a[i].r;
  sort(a+1,a+n+1,cmp);
  sort(b+1,b+n+1);
  for(i=1;i<=n;i++){
    v0[i]=sqrt(1.0*(a[i].l-a[i].r)*(a[i].l-a[i].r)+1.0*B*B);
    v1[i]=min(a[i].l+a[i].r,A+A-a[i].l-a[i].r)+B;
    a[i].r=lower(a[i].r);
  }
  f.build(1,0,n);
  g.build(1,0,n);
  f.change(1,0,n,0,v0[1]);
  g.change(1,0,n,0,v1[1]);
  for(i=1;i<n;i++){
    double x=f.ask(1,0,n,0,a[i+1].r-1),
           y=g.ask(1,0,n,0,a[i+1].r-1);
    if(a[i+1].r<a[i].r){
      f.col1(1,inf);
      g.col1(1,inf);
    }
    f.change(1,0,n,a[i].r,y);
    g.change(1,0,n,a[i].r,x);
    f.add1(1,v0[i+1]);
    g.add1(1,v1[i+1]);
  }
  double ans=min(f.v[1],g.v[1]);
  if(ans>1e28)puts("-1");else printf("%.15f",ans);
}

  

5. Voting

枚举票数然后建图求最小费用最大流。

#include <bits/stdc++.h>
using namespace std ;

typedef long long LL ;

const int MAXN = 1005 ;
const int MAXE = 1000005 ;
const LL INF = 1e18 ;
const LL L = 1e15 ;

struct Edge {
	int v , c , n ;
	LL w ;
	Edge () {}
	Edge ( int v , int c , LL w , int n ) : v ( v ) , c ( c ) , w ( w ) , n ( n ) {}
} ;

Edge E[MAXE] ;
int H[MAXN] , cntE ;
LL d[MAXN] , cost ;
int vis[MAXN] , cur[MAXN] ;
int Q[MAXN] , head , tail ;
int n , K , T ;
int s , t ;
int flow ;
int G[MAXN][15] ;
int res[MAXN] ;

void init () {
	cntE = 0 ;
	memset ( H , -1 , sizeof H ) ;
}

void addedge ( int u , int v , int c , LL w ) {
	E[cntE] = Edge ( v , c , w , H[u] ) ;
	H[u] = cntE ++ ;
	E[cntE] = Edge ( u , 0 , -w , H[v] ) ;
	H[v] = cntE ++ ;
}

int spfa () {
	for ( int i = 0 ; i < MAXN ; ++ i ) {
		d[i] = INF ;
		vis[i] = 0 ;
	}
	head = tail = 0 ;
	Q[tail ++] = s ;
	d[s] = 0 ;
	cur[s] = -1 ;
	while ( head != tail ) {
		int u = Q[head ++] ;
		if ( head == MAXN ) head = 0 ;
		vis[u] = 0 ;
		for ( int i = H[u] ; ~i ; i = E[i].n ) {
			int v = E[i].v ;
			if ( E[i].c && d[v] > d[u] + E[i].w ) {
				d[v] = d[u] + E[i].w ;
				cur[v] = i ;
				if ( !vis[v] ) {
					vis[v] = 1 ;
					Q[tail ++] = v ;
					if ( tail == MAXN ) tail = 0 ;
				}
			}
		}
	}
	if ( d[t] == INF ) return 0 ;
	cost += d[t] ;
	flow ++ ;
	for ( int i = cur[t] ; ~i ; i = cur[E[i ^ 1].v] ) {
		E[i].c -- ;
		E[i ^ 1].c ++ ;
	}
	return 1 ;
}

void mcmf () {
	cost = flow = 0 ;
	while ( spfa () ) ;
}

int check ( int x ) {
	for ( int i = H[T] ; ~i ; i = E[i].n ) {
		int v = E[i].v ;
		if ( v != t ) continue ;
		return E[i ^ 1].c == x ;
	}
}

void getans () {
	for ( int i = 1 ; i <= n ; ++ i ) {
		for ( int j = H[K + 1 + i] ; ~j ; j = E[j].n ) {
			int v = E[j].v ;
			if ( v == s ) continue ;
			if ( E[j].c == 0 ) {
				res[i] = E[j].v ;
				break ;
			}
		}
	}
}

void solve () {
	for ( int i = 1 ; i <= n ; ++ i ) {
		for ( int j = 1 ; j <= K + 1 ; ++ j ) {
			scanf ( "%d" , &G[i][j] ) ;
		}
	}
	LL ans = INF ;
	if ( K == 1 ) {
		ans = 0 ;
		for ( int i = 1 ; i <= n ; ++ i ) {
			if ( G[i][1] < G[i][2] ) {
				ans += G[i][1] ;
				res[i] = 1 ;
			} else {
				ans += G[i][2] ;
				res[i] = 2 ;
			}
		}
		printf ( "%lld\n" , ans ) ;
		for ( int i = 1 ; i <= n ; ++ i ) {
			i > 1 && putchar ( ' ' ) ;
			printf ( "%d" , res[i] ) ;
		}
		puts ( "" ) ;
		return ;
	}
	s = 0 , t = K + 1 + n + 1 ;
	for ( int i = 1 ; i <= n ; ++ i ) {
		init () ;
		for ( int j = 1 ; j <= n ; ++ j ) {
			addedge ( s , K + 1 + j , 1 , 0 ) ;
		}
		for ( int j = 1 ; j <= K ; ++ j ) {
			if ( j != T ) addedge ( j , t , i - 1 , 0 ) ;
			else addedge ( j , t , i , -L ) ;
		}
		addedge ( K + 1 , t , 10000 , 0 ) ;
		for ( int j = 1 ; j <= n ; ++ j ) {
			for ( int k = 1 ; k <= K + 1 ; ++ k ) {
				addedge ( K + 1 + j , k , 1 , G[j][k] ) ;
			}
		}
		mcmf () ;
		//if ( !check ( i ) ) continue ;
		cost += i * L ;
		cost %= L ;
		if ( cost < ans ) {
			ans = cost ;
			getans () ;
		}
	}
	printf ( "%lld\n" , ans ) ;
	for ( int i = 1 ; i <= n ; ++ i ) {
		i > 1 && putchar ( ' ' ) ;
		printf ( "%d" , res[i] ) ;
	}
	puts ( "" ) ;
}


int main () {
	freopen ( "input.txt" , "r" , stdin ) ;
	freopen ( "output.txt" , "w" , stdout ) ;
	while ( ~scanf ( "%d%d%d" , &n , &K , &T ) ) solve () ;
	return 0 ;
}

  

6. Finite automaton

定义状态$i$表示当前读入的数字串模$M$为$i$的状态,然后最小化这个DFA即可。

 

7. Scene management

留坑。

 

8. A system of balance scales

树状数组维护DFS序。

#include<cstdio>
typedef long long ll;
const int N=200010;
int n,m,i,w[N],l[N],r[N],st[N],en[N],dfn,len[N],op,x,y;
ll bit[N];
inline void add(int x,int y){
  if(!x)return;
  for(;x<=dfn;x+=x&-x)bit[x]+=y;
}
inline ll ask(int x){
  ll t=0;
  for(;x;x-=x&-x)t+=bit[x];
  return t;
}
void dfs(int x){
  st[x]=++dfn;
  if(l[x])dfs(l[x]);
  if(r[x])dfs(r[x]);
  en[x]=dfn;
}
int main(){

  freopen("input.txt","r",stdin);
  freopen("output.txt","w",stdout);
  scanf("%d%d",&n,&m);
  for(i=1;i<=n+1;i++){//id=n+i
    scanf("%d",&w[i]);
  }
  for(i=1;i<=n;i++){
    scanf("%d%d%d",&len[i],&l[i],&r[i]);
    if(l[i]<0)l[i]=n-l[i];
    if(r[i]<0)r[i]=n-r[i];
  }
  dfs(1);
  for(i=1;i<=n+1;i++)add(st[n+i],w[i]);
  while(m--){
    scanf("%d%d",&op,&x);
    if(op==1){
      scanf("%d",&y);
      add(st[n+x],y-w[x]);
      w[x]=y;
    }else{
      ll A=ask(en[l[x]])-ask(st[l[x]]-1);
      ll B=ask(en[r[x]])-ask(st[r[x]]-1);
      double ans=1.0*B*len[x]/(A+B);
      printf("%.15f\n",ans);
    }
  }
}

  

9. Karmon be ill

按题意模拟即可。

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<time.h>
#include<assert.h>
#include<iostream>
using namespace std;
typedef long long LL;
typedef pair<int,int>pi;
int n,k;
multiset<int>s1,s2;
bool go1(multiset<int>&S,int x,int &sum){
	if(S.size()<k){
		S.insert(x);
		sum+=x;
		return 1;
	}
	if(*S.begin()<x){
		int tmp=*S.begin();
		sum-=tmp;
		S.erase(S.begin());
		s2.insert(tmp);
		S.insert(x);
		sum+=x;
		return 1;
	}
	return 0;
}
int main(){
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	scanf("%d%d",&n,&k);
	int sum1=0,sum2=0;
	for(int i=1;i<=n;i++){
		int x;scanf("%d",&x);
		if(!go1(s1,x,sum1))s2.insert(x);
		if(s1.size()>=k){
			printf("%d%c",sum1,i==n?'\n':' ');
		}
	}
	return 0;
}

  

10. Battle City Online

留坑。

 

11. Test generation

考虑模$P$意义下的Hash,按Hash值排序后双指针即可。

#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<queue>
#include<time.h>
#include<assert.h>
#include<iostream>
using namespace std;
typedef long long LL;
typedef pair<int,int>pi;
char s[100020];
int P,rev,ls;
int pw[100020];
int h[100020];
pi a[100020],b[100020];
map<int,int>Loc,Mp;
int powmod(int x,int y,int mod){
	int ret=1;
	while(y){
		if(y&1)ret=1LL*ret*x%mod;
		y>>=1;
		x=1LL*x*x%mod;
	}
	return ret;
}
int main(){
	freopen("input.txt","r",stdin);
	freopen("output.txt","w",stdout);
	scanf("%s",s+1);
	ls=strlen(s+1);
	int _;scanf("%d%d",&_,&P);
	rev=powmod(10,P-2,P);
	pw[0]=1;
	for(int i=1;i<=ls;i++)pw[i]=1LL*pw[i-1]*rev%P;
	while(_--){
		int x;scanf("%d",&x);
		int cur=0;
		int resl=-1,resr=-1;
		LL ans=0;
		b[0]=pi(0,0);
		for(int i=1;i<=ls;i++){
			cur=(1LL*cur*10+s[i]-'0')%P;
			int ned=(cur-x+P)%P;
			ned=1LL*ned*pw[i]%P;
			a[i-1]=pi(ned,i);
			b[i]=pi(1LL*cur*pw[i]%P,i);
		}
		sort(a,a+ls);
		sort(b,b+ls);
		for(int i=0,j=0;i<ls&&j<ls;){
			if(a[i].first==b[j].first){
				int t1,t2;
				for(t1=i,t2=j;t1<ls&&a[t1].first==a[i].first;t1++){
					while(t2<ls&&(b[t2].first==b[j].first)&&(b[t2].second<a[t1].second))t2++;
					if(t2>j){
						resl=b[j].second;
						resr=a[t1].second;
						ans+=t2-j;
					}
				}
				i=t1;
			}	
			else {
				if(a[i].first>b[j].first)j++;
				else i++;
			}
		}
		if(resl<0)puts("0 0 0");
		else printf("%lld %d %d\n",ans,resl+1,resr);
	}
	return 0;
}

  

posted @ 2017-04-06 22:53  Claris  阅读(440)  评论(0编辑  收藏  举报