Atcoder Grand Contest 19 题解

来源:互联网 发布:hk域名 编辑:程序博客网 时间:2024/06/07 06:05

入坑atcoder,之前打过几场但是都是什么beginner test,,水的一匹。
tourist出的题目,害怕,向老大哥低头。

A
比较简单的水题。。贪心判就好了,反正四个东西是可以互相转化的。

#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=1e5+5;typedef long long ll;ll n;ll a[5],b[5];int main(){    scanf("%lld%lld%lld%lld",&b[1],&b[2],&b[3],&b[4]);    scanf("%lld",&n);    a[1]=1,a[2]=2,a[3]=4,a[4]=8;    n*=4;    ll ans=0;    while (n>0)    {        ll m=0,s=0;        fd(i,4,1)        if (n>=a[i])        {            m=n%a[i];            s=n/a[i];            n=m;            ll tmp=s*b[i],j=i;            while (j>1)tmp=min(tmp,(s*=2)*b[j-1]),j--;            ans+=tmp;        }    }    printf("%lld\n",ans);}

B
也挺水,但是卡了一会儿,菜的一匹。
根据题目要求,i<=j,可以发现i=j没卵用去掉。
然后剩余的,我就脑抽了,求不合法方案数很明显,问题是我居然一开始想的是回文串(智障),搞了半天manacher,最后发现只要端点不同就会GG,所以是个n^2水题。

#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=3e5+5;typedef long long ll;char s[N],s1[N];int vis[28];int n,m;ll ans;int f[N];int main(){    scanf("%s",s+1);    n=strlen(s+1);    fo(i,1,n)    {        vis[s[i]-'a'+1]++;    }    fo(i,1,n)    {        int c=s[i]-'a'+1;        vis[c]--;        ans+=i-1-(vis[c]);    }    printf("%lld\n",ans+1);}

C
第一眼看题觉得是个水题,特殊点处理一下就好。
然后看见数据范围觉得很一颗赛艇。。x,y<=1e8不可能bfs
n<=2e5不可能spfa,哇有鬼。。
然后想是不是应该把点全部转化成左下右上然后跑个最短路,点数还是会超。
然后我硬是没想到lis。。
把所有点从左下到右上搞一下,然后求个lis。
正确性显然了,我要让经过的特殊点最多,横纵坐标又要递增(非严格),所以lis很符合。。

#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define Pi acos(-1.0)#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)using namespace std;const int N=3e5+5;int n,m;struct node{    int x,y;}a[N];int cnt,q[N],len;double ans;bool flag;bool cmp(node a,node b){    return a.x<b.x;}int main(){    int x1,y1,y2,x2;    scanf("%d%d%d%d",&x1,&y1,&x2,&y2);    if (x2<x1)swap(x1,x2),swap(y1,y2);    if (y1>y2)y1=-y1,y2=-y2,flag=1;    scanf("%d",&n);    fo(i,1,n)    {        int x,y;        scanf("%d%d",&x,&y);        if (flag)y=-y;        if (x>=x1&&x<=x2&&y>=y1&&y<=y2)a[++cnt]=(node){x,y};    }    sort(a+1,a+1+cnt,cmp);    fo(i,1,cnt)    {        int l=1,r=len,ans=0;        while (l<=r)        {            int mid=(l+r)>>1;            if (a[i].y>q[mid])l=mid+1,ans=mid;            else r=mid-1;        }        if (ans==len)q[++len]=a[i].y;        else q[ans+1]=min(q[ans+1],a[i].y);    }    ans=(x2-x1+y2-y1)*100.0;    if (x1==x2||y1==y2)    {        if (cnt)ans+=10.0*Pi-20.0;    }    else    {        ans-=(20-5.0*Pi)*len;        if (len==min(x2-x1,y2-y1)+1)ans+=5*Pi;    }    printf("%.13lf\n",ans);    return 0; } 

D
stl题(???)
反正看见A的人STL用到飞起,让我这个没用过vector的心情复杂。。
具体的话应该是枚举偏移量?然后直接暴力求贡献。。感觉像是那种贪心模拟,但是细节鬼畜。
时间复杂度n^2log。

#include <bits/stdc++.h>using namespace std;const int N = 2017;char a[N], b[N];char x[N];pair<int, int > ve[N];int main() {  scanf("%s", a);  scanf("%s", b);  int n = strlen(a);  int ans = 1e8;  for (int sl = -n; sl <= n; sl++) {    int cnt = 0;    for (int i = 0; i < n; i++) {      x[i] = a[(i+n-sl) % n];      cnt += x[i] != b[i];      ve[i] = make_pair(-1e8, 1e8);    }    if (cnt == 0)      ans = min(ans, abs(sl));    int last = -1;    for (int i = 0; i < 3 * n; i++) {      if (b[i % n] == '1')        last = i;      if (x[i % n] != b[i % n]) {        if (last == -1) continue;        ve[i % n].first = max(min(last - i + sl, 0), ve[i % n].first);      }    }    last = -1;    for (int i = 3 * n; i >= 0; i--) {      if (b[i % n] == '1')        last = i;      if (x[i % n] != b[i % n]) {        if (last == -1) continue;        ve[i % n].second = min(max(last - i + sl, 0), ve[i % n].second);      }    }    vector<pair<int, int > > vv;    for (int i = 0; i < n; i++) if (b[i] != x[i])      vv.push_back(ve[i]);    sort(vv.begin(), vv.end());    int ri = max(0, sl);    for (int le = -n, j = 0; le <= min(sl, 0); le++) {      while (j < vv.size() && vv[j].first < le) ri = max(ri, vv[j].second), j++;      ans = min(ans, cnt + ri-le + ri - le -abs(sl));    }  }  if (ans >= 1e8)    ans = -1;  printf("%d\n", ans);  return 0;}

E,F待填坑~~

原创粉丝点击