• 2013-2014 ACM ICPC Central European Regional Contest (CERC 13)


    这套题的思维量比较少,但是有些题很毒瘤 Orz。

    https://codeforces.com/gym/100299

    题目按照我过题顺序排的:

    L

    模拟。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    
    using pii = pair<int, int>;
    using ll = long long;
    
    inline void read(int &x){
        int s=0; x=1;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
        while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        x*=s;
    }
    
    int main(){
    	int T; cin>>T;
    	while(T--){
    		int n; cin>>n;
    		cout<<(1<<n)-1<<endl;
    	}
    	return 0;
    }
    

    B

    模拟,字符串处理。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    
    using pii = pair<int, int>;
    using ll = long long;
    
    inline void read(int &x){
        int s=0; x=1;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
        while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        x*=s;
    }
    
    string s[110], tmp[4];
    map<string, bool> vis;
    
    int main(){
    	int T; cin>>T; getchar();
    	while(T--){
    		string t; 
    		int tot=0;
    		while(getline(cin, t)){
    			if(t=="what does the fox say?") break;
    			s[++tot]=t;
    		}
    		
    		vis.clear();
    		rep(i,2,tot){
    			int cur=0;
    			stringstream ssin(s[i]);
    			while(ssin>>t) tmp[++cur]=t;
    			vis[tmp[3]]=true;
    		}
    		
    		stringstream ssin(s[1]);
    		while(ssin>>t) if(!vis[t]) cout<<t<<' ';
    		cout<<endl;
    	}
    	return 0;
    }
    

    F

    搜索。

    注意题意说的是:一步棋中用一个棋子连续吃掉几个棋子。通过向前或向后的跳跃来吃子也是合法的。

    所以我们可以对于棋盘上每一个白棋进行搜索,并找出它们在所有的决策中能够吃掉的最多黑棋,那么这个过程搜索 + 回溯就可以解决了。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    
    using pii = pair<int, int>;
    using ll = long long;
    
    inline void read(int &x){
        int s=0; x=1;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
        while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        x*=s;
    }
    
    const int n=10, N=15;
    
    char g[N][N];
    
    int dfs(int x, int y){
    	int res=0;
    	for(int i=-1; i<=1; i+=2) for(int j=-1; j<=1; j+=2){
    		int kx=i+x, ky=j+y;
    		if(kx<1 || kx>n || ky<1 || ky>n) continue;
    		if(g[kx][ky]!='B') continue;
    		int X=x+2*i, Y=y+2*j;
    		if(X<1 || X>n || Y<1 || Y>n) continue;
    		if(g[X][Y]!='#') continue;
    		// ok
    		g[kx][ky]='#';
    		res=max(res, dfs(X, Y)+1);
    		g[kx][ky]='B';
    	}
    	return res;
    }
    
    int main(){
    	int T; cin>>T;
    	while(T--){
    		rep(i,1,n) rep(j,1,n) cin>>g[i][j];
    		int res=0;
    		rep(i,1,n) rep(j,1,n) if(g[i][j]=='W'){
    			g[i][j]='#';
    			res=max(res, dfs(i, j));
    			g[i][j]='W';
    		}
    		cout<<res<<endl;
    	}
    	return 0;
    }
    
    

    I

    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    
    using pii = pair<int, int>;
    using ll = long long;
    
    inline void read(int &x){
        int s=0; x=1;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
        while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        x*=s;
    }
    
    const int N=10010;
    
    int w[N], n;
    
    struct Msg{
    	int x, y;
    }res[N*55];
    int tot;
    
    int main(){
    	int T; cin>>T;
    	while(T--){
    		cin>>n;
    		rep(i,1,n) read(w[i]);
    		
    		tot=0;
    		rep(i,1,n){
    			int p;
    			rep(j,i,n) if(w[j]==i){
    				p=j;
    				break;
    			}
    
    			if(p==i) continue;
    			
    			while(i!=p){
    				if(p-i&1){
    					res[++tot]={i, p};
    					int mid=p+i>>1;
    					rep(j,i,mid) swap(w[j], w[j+(p-i+1)/2]);
    					p=mid;
    				}
    				else{
    					res[++tot]={i+1, p};
    					int mid=p+i+1>>1;
    					rep(j,i+1,mid) swap(w[j], w[j+(p-i)/2]);
    					p=mid;
    				}
    			}
    		}
    		
    		cout<<tot<<endl;
    		rep(i,1,tot) printf("%d %d
    ", res[i].x, res[i].y);
    	}
    	return 0;
    }
    

    C

    注意到当固定右端点 (i) 时,其左边最多有 (log~i) 段不同的 (gcd) 值,而且这个值向左递减,所以我们可以用二分来向左跳并更新答案。

    至于区间 (gcd) 值用 ST 表维护就行了。

    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    
    using pii = pair<int, int>;
    using ll = long long;
    
    #define int long long
    
    inline void read(int &x){
        int s=0; x=1;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
        while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        x*=s;
    }
    
    const int N=1e5+5;
    
    int n, w[N];
    
    int st[N][25], Log[N];
    
    int gcd(int a, int b){
    	return b? gcd(b, a%b): a;
    }
    
    void build(){
    	rep(i,2,N-1) Log[i]=Log[i/2]+1;
    	rep(j,0,20) for(int i=1; i+(1<<j)-1<=n; i++){
    		if(!j) st[i][0]=w[i];
    		else st[i][j]=gcd(st[i][j-1], st[i+(1<<j-1)][j-1]);
    	}
    }
    
    int query(int l, int r){
    	int k=Log[r-l+1];
    	return gcd(st[l][k], st[r-(1<<k)+1][k]);
    }
    
    int find(int val, int l, int r){
    	int R=r;
    	while(l<r){
    		int mid=l+r>>1;
    		if(query(mid, R)>=val) r=mid;
    		else l=mid+1;
    	}
    	return l;
    }
    
    signed main(){
    	int T; cin>>T;
    	while(T--){
    		cin>>n;
    		rep(i,1,n) read(w[i]);
    		
    		build();
    		
    		int res=0;
    		rep(i,1,n){
    			int r=i;
    			while(r){
    				int val=query(r, i); 
    				int l=find(val, 1, i);
    				res=max(res, (i-l+1)*val);
    				r=l-1;
    			}
    		}
    		
    		cout<<res<<endl;
    	}
    	
    	return 0;
    }
    

    K

    我将这题写成大模拟了(悲。

    思路很简单:

    • 将所给的关系建成图
    • 若图上存在环,直接用环构造即可。
    • 不存在环则在 DAG 上找到最长链(长度记为 (sz)​),构造出的方阵长为 ((sz+1)/2)。​​
    #include<bits/stdc++.h>
    using namespace std;
    
    #define debug(x) cerr << #x << ": " << (x) << endl
    #define rep(i,a,b) for(int i=(a);i<=(b);i++)
    #define dwn(i,a,b) for(int i=(a);i>=(b);i--)
    
    using pii = pair<int, int>;
    using ll = long long;
    
    inline void read(int &x){
        int s=0; x=1;
        char ch=getchar();
        while(ch<'0' || ch>'9') {if(ch=='-')x=-1;ch=getchar();}
        while(ch>='0' && ch<='9') s=(s<<3)+(s<<1)+ch-'0',ch=getchar();
        x*=s;
    }
    
    const int n=26, N=35;
    
    int g[N][N];
    int m;
    
    int get(char t){
    	return t-'a'+1;
    }
    
    char rget(int t){
    	return t-1+'a';
    }
    
    int res[N][N];
    
    int deg[N];
    int q[N];
    int tt, hh;
    
    int f[N], pre[N];
    vector<int> lk; // link
    bool topsort(){
    	tt=-1, hh=0;
    	int cnt=0;
    	rep(i,1,n) if(!deg[i]) q[++tt]=i, cnt++, f[i]=1;
    	
    	while(tt>=hh){
    		int u=q[hh++]; 
    		rep(v,1,n) if(v!=u && g[u][v]){
    			if(--deg[v]==0){
    				q[++tt]=v, cnt++;
    				if(f[v]<f[u]+1){
    					f[v]=f[u]+1;
    					pre[v]=u;
    				}
    			}
    		}
    	}
    	return cnt==n;
    }
    
    bool vis[N];
    int stk[N], top;
    bool gotLoop;
    void dfs(int u, int root){
    	if(gotLoop) return;
    	if(vis[u]){
    		if(root==u){
    			gotLoop=true;
    		}
    		return;
    	}
    	
    	stk[++top]=u;
    	vis[u]=true;
    	
    	rep(v,1,n) if(v!=u && g[u][v]){
    		dfs(v, root);
    		if(gotLoop) return;
    	}
    	top--;
    	vis[u]=false;
    }
    
    void check(int sz){
    	bool ok=true;
    	rep(i,1,sz) rep(j,1,sz-1) if(!g[res[i][j]][res[i][j+1]]) ok=false;
    	rep(i,1,sz) rep(j,1,sz-1) if(!g[res[j][i]][res[j+1][i]]) ok=false;
    	if(ok) cerr<<"AC"<<endl;
    	else cerr<<"WA"<<endl;
    }
    
    int main(){
    	int T; cin>>T;
    	while(T--){
    		cin>>m;
    		rep(i,1,n) rep(j,1,n) g[i][j]=1;
    		while(m--){
    			string t; cin>>t;
    			int u=get(t[0]), v=get(t[1]);
    			g[u][v]=0;
    		}
    
    		bool ed=false; int rec; // self loop
    		rep(i,1,n) if(g[i][i]) ed=true, rec=i;
    		if(ed){
    			rep(i,1,20){
    				rep(j,1,20) cout<<rget(rec);
    				cout<<endl;
    			}
    			continue;
    		}
    		
    		rep(i,1,n) deg[i]=pre[i]=f[i]=vis[i]=0;
    		rep(i,1,n) rep(j,1,n) if(g[i][j]) deg[j]++;
    
    		if(topsort()){
    			int u, val=0;
    			rep(i,1,n) if(f[i]>val) val=f[i], u=i;
    			lk.clear();
    			while(u){
    				lk.push_back(u);
    				u=pre[u];
    			}
    			reverse(begin(lk), end(lk));
    			int sz=(int)lk.size()+1>>1;
    			rep(i,1,sz) rep(j,1,sz) res[i][j]=lk[i+j-2];
    			rep(i,1,sz){
    				rep(j,1,sz) cout<<rget(res[i][j]);
    				cout<<endl;
    			}
    
    			// check(sz);
    		}
    		else{
    			gotLoop=false;
    			rep(i,1,n){
    				if(gotLoop) break;
    				rep(j,1,n) vis[j]=false;
    				top=0;
    				dfs(i, i);
    			}
    
    			rep(i,1,20) rep(j,1,20) res[i][j]=stk[(i+j)%top+1];
    			rep(i,1,20){
    				rep(j,1,20) cout<<rget(res[i][j]);
    				cout<<endl;
    			}
    			
    			// check(20);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    【转】关于维生素的那些事
    【转】MaBatis学习---源码分析MyBatis缓存原理
    【转】Spring学习---Bean配置的三种方式(XML、注解、Java类)介绍与对比
    【转】Java学习---垃圾回收算法与 JVM 垃圾回收器综述
    Qt 中的对象模型(Object Model)
    The Property System
    Qt--core模块概述
    QtCore概述
    在Android Studio中下载Android SDK的两种方式(Android Studio3.0、windows)
    同一个进程的多个线程堆栈共享状况
  • 原文地址:https://www.cnblogs.com/Tenshi/p/15500994.html
Copyright © 2020-2023  润新知