红红火火恍恍惚惚,哈哈哈哈上分喽,上了60整o(* ̄▽ ̄*)ブ,蓝蓝的~
话说昨晚打的也并不十分顺利,CD都WA了好几发QAQ索性没挂终测不然真是凉了~
A、Palindromic Twist
http://codeforces.com/contest/1027/problem/A
题意:一串字符串,每个字符都必须上或下移动一个位子,AZ只有一种移动方法。求能否构成回文串
思路:大水题,前后对称位置ASCLL值均差2或0,有一个不符合的就不可以,看了几个被hack的代码,有的是考虑了az可以互换。。但实际不可以
代码:
#include<bits/stdc++.h>
using namespace std;
char ch[105];
int T,n,ok,l;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ok=1;
scanf("%s",ch);
for(int i=0;i<n/2;i++)
{
l=ch[i]-ch[n-1-i];
if(l<0) l=-l;
if(l==2||l==0) continue;
else {ok=0;break;}
}
if(ok) printf("YES\n");
else printf("NO\n");
}
}
B:Numbers on the Chessboard
http://codeforces.com/contest/1027/problem/B
题意:n*n的矩阵,从上往下,从左到右先将行列坐标为偶数的格子依次填上数,再将剩下的填上数、q次询问[x,y]格内的数字
思路:这个我是粉丝种情况讨论的,但是赛后看了别人的代码,,自己还是想错 了,将格子依次编号,就可以看出,和为偶数与奇数的相邻,所以可以直接考虑第((x-1)*n+y)个格子,,代码一看就懂。。是自己傻了,白白浪费了时间
大佬代码:
#include<iostream>
using namespace std;
typedef long long ll;
ll n,q,a,b,ans;
int main(){
cin>>n>>q;
while(q--){
cin>>a>>b;
ans=(a-1)*n+b+1;
if((a+b)%2)ans+=n*n;
cout<<ans/2<<endl;
}
}
自己的麻烦代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
long long n,q,x,y,ans;
int main()
{
scanf("%lld%lld",&n,&q);
while(q--)
{
scanf("%lld%lld",&x,&y);
if(n%2==0)
{
if((x+y)%2==0)
{
ans=(x-1)/2*n;
if(x%2==0) ans+=n/2+y/2;
else ans+=y/2+y%2;//cout<<x<<" "<<y<<" "<<ans<<endl;
}
else
{
ans=n*n/2+(x-1)/2*n;
if(x%2==0) ans+=n/2+y/2+y%2;
else ans+=y/2;
}
}
else
{
if((x+y)%2==0)
{
ans=(x-1)/2*n;
if(x%2==0) ans+=n/2+1+y/2;
else ans+=y/2+y%2;
}
else
{
ans=n*n/2+1+(x-1)/2*n;
if(x%2==0) ans+=n/2+y/2+y%2;
else ans+=y/2;
}
}
printf("%lld\n",ans);
}
}
C、 Minimum Value Rectangle
http://codeforces.com/contest/1027/problem/C
题意:给出n根木棍的长度,求从中选择4根,能组成最小的(周长的平方/面积)的值的4根的长度
思路:带入长宽化简,就可以得出是要求(a/b+b/a)的最小值,就是将长度数量多于两根的取出来,加入set,然后依次往外取,相邻两根比较队化简后的对应值一直更新最小值即可。
不过这个题真的有毒,,一开始多加了一个break,导致输入没输完导致WA,,然后又因为memset TLE了。。。1e4的数组开成了1e5的,不然比赛的时候不会T,,但是会挂终测。。。幸好当时开大了,,不然真的要挂,,真是幸运~~取消memset就是记录一下n个数,最后重置一下就可以
代码:
#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
int T,n,num[10005],x,y,ans[5],ok,a[1000005];
int main()
{
set<int>q;
scanf("%d",&T);
while(T--)
{
ok=0;
q.clear();
//memset(num,0,sizeof(num));
scanf("%d",&n);
ans[0]=-1;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
x=a[i];
num[x]++;
if(num[x]==2) q.insert(x);
if(num[x]==4) {ans[0]=x;ans[1]=x;ok=1;}
}
for(int i=1;i<=n;i++) num[a[i]]=0;
if(ans[0]!=-1)
{
printf("%d %d %d %d\n",ans[0],ans[0],ans[1],ans[1]);
}
else
{
x=*q.begin();
q.erase(q.begin());
double pp=10000000000.0;
while(!q.empty())
{
y=*q.begin();
q.erase(q.begin());
if(4*(x*(1.0)/y)+4*(y*(1.0)/x)+8<pp)
{
pp=4*(x*(1.0)/y)+4*(y*(1.0)/x)+8;
// cout<<pp<<endl;
ans[0]=x;
ans[1]=y;
}
x=y;
}
printf("%d %d %d %d\n",ans[0],ans[0],ans[1],ans[1]);
}
}
}
D、Mouse Hunt
http://codeforces.com/contest/1027/problem/D
题意:n个房间,一只老鼠,老鼠到达房间i,下一次会到达房间a【i】,若a[i]==i,老鼠原地不动,在每个房间放捕鼠器都会花费对应价值,求使老鼠不论从何房间进入都能被抓到的最小花费
思路:这个有点像那场多校狼人杀的那个游戏的那个题,(题解)都是每个点出度只有1,这个题只需要再每条边的终点放捕鼠器就可以,有环的话就要选环上最小的一个房间,再就是要注意由边进环的情况,例如1->2->3->4->5->3.就是处理略微麻烦,,但是不难,,就是又傻了,,忘记判断最后纯环的情况,白WA了三发。。。心痛
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+5;
int T,n,c[MAX],fa[MAX],num,in[MAX],out[MAX],look[MAX],ss[MAX];
long long ans;
void PP(int rt,int ff,int ok,int minn)
{
//zz[rt]=1;
look[rt]=1;
if(ok&&rt==ff) {ans+=minn;return;}
PP(fa[rt],ff,1,min(minn,c[rt]));
}
void dfs(int rt,int id)
{
//cout<<rt<<endl;
if(ss[rt]!=0&&ss[rt]!=id&&look[rt]) return;
ss[rt]=id;
//if(zz[rt]) return;
if(look[rt]) {PP(rt,rt,0,0x3f3f3f3f);return;}
look[rt]=1;
if(fa[rt]==rt) {ans+=c[rt];return;}
dfs(fa[rt],id);
}
int main()
{
scanf("%d",&n);
ans=0;
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
for(int i=1;i<=n;i++)
{
scanf("%d",&fa[i]);
if(fa[i]==i) {continue;}
in[fa[i]]++;
}
for(int i=1;i<=n;i++)
{
if(in[i]==0) dfs(i,i);
}
for(int i=1;i<=n;i++)
{
if(look[i]==0) PP(i,i,0,0x3f3f3f3f);
}
printf("%lld\n",ans);
}