zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 032

      A:倒序考虑,每次删除最后一个合法数即可,正确性显然。好久没有atcoder比赛我又忘了评测机并没有define online_judge白交了一发。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 110 
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,a[N],ans[N];
    signed main()
    {
    	n=read();
    	for (int i=1;i<=n;i++) a[i]=read();
    	for (int i=n;i>=1;i--)
    		for (int j=i;j>=1;j--)
    		if (a[j]==j)
    		{
    			for (int k=j;k<i;k++) a[k]=a[k+1];
    			ans[i]=j;
    			break;
    		}
    	for (int i=1;i<=n;i++) if (!ans[i]) {cout<<-1;return 0;}
    	for (int i=1;i<=n;i++) cout<<ans[i]<<endl;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      B:容易发现当n%4==0时,可以将图划分成一个二分图,使其两边和相等,然后中间所有边都连上即可。类似的可以发现,只要将图划分成若干和相同的集合即可。那么根据n的奇偶性讨论一下就好了,偶数时小的和大的两两匹配,奇数时把n单独列为一个集合同样两两匹配。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    #define ll long long
    #define N 110 
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n;
    vector<int> a[N];
    signed main()
    {
    	n=read();
    	int s=n*(n+1)/2;
    	if (n%2==0)	for (int i=1;i<=n/2;i++) a[i].push_back(i),a[i].push_back(n-i+1);
    	if (n%2==1)
    	{
    		for (int i=1;i<=n/2;i++) a[i].push_back(i),a[i].push_back(n-i);
    		a[(n+1)/2].push_back(n);
    	}
    	int ans=0;
    	for (int i=1;i<=(n+1)/2;i++)
    		for (int j=i+1;j<=(n+1)/2;j++)
    		if (i!=j) ans+=a[i].size()*a[j].size();
    	cout<<ans<<endl;
    	for (int i=1;i<=(n+1)/2;i++)
    		for (int j=i+1;j<=(n+1)/2;j++)
    		if (i!=j) 
    			for (int x=0;x<a[i].size();x++)
    				for (int y=0;y<a[j].size();y++)
    				cout<<a[i][x]<<' '<<a[j][y]<<endl;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      C:首先显然必须得存在欧拉回路。那么即要把跑出来的欧拉回路拆成三个回路。显然在欧拉回路所经过的点序列中,找到一个首尾点均相同的段抽出来,就是一个回路。那么检查序列中是否有点出现三次或以上,若有显然有解;否则检查出现两次的点,这样的点需要有两个或以上,如果其中两个点能构成不相交的段则有解。注意到若有至少三个点一定有解,稍微讨论一下即可证明。那么只需要考虑有两个点的情况,判一下是否相交。实际上并不需要跑欧拉回路,通过度数讨论一下即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 100010
    #define id(i) (((i)+1)/2)
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,p[N],degree[N],cnt[N],t,stk[N<<1],top,tot;
    struct data{int to,nxt;
    }edge[N<<1];
    bool flag[N];
    void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
    void dfs(int k,int t)
    {
    	if (k==t) {tot++;return;}
    	flag[k]=1;
    	for (int i=p[k];i;i=edge[i].nxt)
    	if (!flag[edge[i].to]||edge[i].to==t)
    	{
    		dfs(edge[i].to,t);
    	}
    }
    signed main()
    {
    	n=read(),m=read();
    	for (int i=1;i<=m;i++)
    	{
    		int x=read(),y=read();
    		degree[x]++,degree[y]++;
    		addedge(x,y),addedge(y,x);
    	}
    	for (int i=1;i<=n;i++) if (degree[i]&1) {cout<<"No";return 0;}
    	for (int i=1;i<=n;i++) if (degree[i]>=6) {cout<<"Yes";return 0;}
    	int cnt=0;
    	for (int i=1;i<=n;i++) if (degree[i]>=4) {cnt++;}
    	if (cnt>=3) {cout<<"Yes";return 0;}
    	if (cnt<=1) {cout<<"No";return 0;}
    	int x=0,y=0;for (int i=1;i<=n;i++) if (degree[i]>=4) if (x) y=i;else x=i;
    	dfs(x,y);
    	if (tot==2) cout<<"Yes";else cout<<"No";
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      D:将移动序列看成移动一个数,进一步看成将一个数放到一个实数位置上,代价根据是向左还是向右还是不动不同。这样dp就很显然了,即将所有数从小到大排序(相同的数按初始位置排序)后,设f[i][j]为第i个数放在第j段时,前i个数的最小代价,转移显然。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 5010
    #define inf 1000000000000000ll
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,A,B;
    struct data
    {
    	int x,y;
    	bool operator <(const data&a) const
    	{
    		return x<a.x||x==a.x&&y<a.y;
    	}
    }a[N];
    ll f[N][N<<1];
    signed main()
    {
    	n=read(),A=read(),B=read();
    	for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=i;
    	sort(a+1,a+n+1);
    	for (int i=1;i<=n;i++)
    	{
    		ll s=inf;
    		for (int j=0;j<=n*2;j++)
    		{
    			s=min(s,f[i-1][j]);
    			if (j&1)
    			{
    				f[i][j]=s+((j+1>>1)==a[i].y?0:((j+1>>1)<a[i].y?B:A));
    			}
    			else
    			{
    				f[i][j]=s+(((j>>1)<a[i].y?B:A));
    			}
    		}
    	}
    	ll ans=inf;
    	for (int i=0;i<=n*2;i++) ans=min(ans,f[n][i]);
    	cout<<ans;
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      E:如果不考虑%m的话显然小的和大的配对。可以证明若将需要减m的对和不需要减m的对分成两组,一定存在最优方案使得不需要减m的是一段前缀而需要减m的是一段后缀,并且其分别满足上述贪心策略。具体讨论几种情况可以发现交换不会更劣。显然前后缀的分界点确定则方案确定,注意到分界点移动时两边答案单调移动且方向相同,那么二分找到最靠前的合法分界点(即满足上述条件)即可。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define N 200010 
    #define inf 2000000001
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
    	int x=0,f=1;char c=getchar();
    	while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    	while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    	return x*f;
    }
    int n,m,a[N],ans;
    int calc_head(int k)
    {
    	int s=0;
    	for (int i=1;i<=k/2;i++) 
    	{
    		if (a[i]+a[k-i+1]>=m) return inf;
    		s=max(s,a[i]+a[k-i+1]);
    	}
    	return s;
    }
    int calc_tail(int k)
    {
    	int s=0;
    	for (int i=k;i<=n;i++)
    	{
    		if (a[i]+a[n-(i-k)]<m) return inf;
    		s=max(s,a[i]+a[n-(i-k)]-m);
    	}
    	return s;
    }
    signed main()
    {
    	n=read()*2,m=read();
    	for (int i=1;i<=n;i++) a[i]=read();
    	sort(a+1,a+n+1);
    	int x;
    	int L=0,R=n/2;
    	while (L<=R)
    	{
    		int mid=L+R>>1;
    		if (calc_tail(mid*2+1)==inf) L=mid+1;
    		else R=mid-1,x=mid*2;
    	}
    	cout<<max(calc_head(x),calc_tail(x+1));
    	return 0;
    	//NOTICE LONG LONG!!!!!
    }
    

      F:咕

      result:rank 177 rating +46

  • 相关阅读:
    myeclipse 8.5 workspace无故初始化
    过 DNF TP 驱动保护(二)
    LogMiner
    过 DNF TP 驱动保护(一)
    驱动列举进程输出到应用层
    [转]hookQQAPI拦截QQ聊天记录有图有码
    Oracle Grid 下载地址
    Oracle 分区表 总结
    NtQuerySystemInformation的使用
    oracle asm之添加和修改asm磁盘组
  • 原文地址:https://www.cnblogs.com/Gloid/p/10604980.html
Copyright © 2011-2022 走看看