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