zoukankan      html  css  js  c++  java
  • XVII Open Cup named after E.V. Pankratiev. GP of Siberia, Division 1

    1. Ski race

    枚举枚举倍数判断即可。时间复杂度$O(nlog 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
    " , 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(nlog 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
    " , 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
    " , 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
    ",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?'
    ':' ');
    		}
    	}
    	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
    ",ans,resl+1,resr);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    HDOJ2553 N皇后问题
    NYOJ284 坦克大战 BFS/优先队列
    NYOJ14 会场安排问题 贪心
    POJ1664 放苹果
    NYOJ119 士兵杀敌(三) RMQ
    POJ3264 Balanced Lineup RMQ/线段树
    POJ1127 Jack Straws
    HDOJ1128 Self Numbers
    水晶报表CrystalReports很强大也很简单!
    PetShop项目学习笔记(三)
  • 原文地址:https://www.cnblogs.com/clrs97/p/6675883.html
Copyright © 2011-2022 走看看