Atcoder Grand Contest 019 总结

来源:互联网 发布:ifunbox mac 破解版 编辑:程序博客网 时间:2024/06/01 16:43

这把AGC打的还不错233..这次的C题,我在两个小时里面WA了10次,在最后40秒的时候绝望交了一发C竟然过了..运气真好233
最终rank:223
rating+=197
目前rating:1591(Fighting!!!)

A - Ice Tea Store

题意:给你一共4种杯子,他们的容量分别是0.25,0.5,1,2,他们的单价分别是a,b,c,d,现在给你要买的茶的数量n,问你如何买这些杯子才能做到花费最小且恰好全部装完(不多不少)。
P.S.所有数均为整数。
思路&&题解:注意到n为整数,那我们就可以把0.25的单价乘上4,把0.5的单价乘上2,然后将他们两个与容量为1的单价取最小作为容量为1的单价cnt1,然后再将这个最小值乘2,与容量为2的单价做比较,得到更小的值作为容量为2的单价cnt2,那最终结果就是(n%2)×cnt1+(n÷2)×cnt2就行了

代码如下:

#include<bits/stdc++.h>using namespace std;typedef long long ll;ll sum=0;ll n,one,two;ll a[5];int main() {    for(int i=1;i<=4;i++)        cin>>a[i];    a[1]*=4LL;    a[2]*=2LL;    cin>>n;    one=min(a[1],min(a[2],a[3]));    two=min(a[4],one*2);    sum=(n/2)*two+(n%2)*one;    cout<<sum<<endl;    return 0;}

B - Reverse and Compare

题意:给你一串只由小写字母组成的字符串,你拥有最多一次翻转一个区间的机会,问你最多能得到多少个不同的字符串。
思路&&题解:我们可以看到要是一个子串首尾字母相同,如arta,那么翻转区间[1,4]和翻转区间[2,3]是一样的,所以我们认为只要出现相同字母,那么就重复,之后再求一下前缀和就行了。

代码如下:

#include<bits/stdc++.h>using namespace std;const int maxn=200050;typedef long long ll;string s;int cnt[26][maxn];int main() {    cin>>s;    for(int i=0;i<s.length();i++) {        for(int j=0;j<26;j++)            cnt[j][i+1]=cnt[j][i];        cnt[s[i]-'a'][i+1]++;    }    ll sum=1;    for(int i=0;i<s.length();i++)        sum+=(i+1)-cnt[s[i]-'a'][i+1];    cout<<sum<<endl;    return 0;}

C - Fountain Walk

题意:有一个1e8×1e8的方格图,给出坐标x,y,xx,yy,表示有个人想从起点x,y走到终点xx,yy,临近的两个点之间的距离为100m,而有几个点上可能有一个半径为10m的圆,经过这个点时只能走圆上的弧,且没有两个圆会在同一条直线上。问你从起点到中点的最短路。
思路&&题解:首先我们可以知道走过圆的时候,走90°的弧可以减少路程,而走180°的弧会增加路程。所以除了起点和终点在同一条线上的情况,是必须会走180°的弧的;还有一种情况后面讲。所以先特判当起点终点在同一直线上时直接扫一遍就行了。而不是找同一直线上的话,如果起点的x坐标大于终点,那么交换一下,因为从起点到终点和从终点到起点的最短路是一样的。所以之后就是先扫一遍,把在起点到终点组成的矩形里的圆给拿出来,然后就nlogn跑一次最长子序列就行了。但是注意:当最长子序列长度等于起点终点横坐标差加一或者纵坐标差加一时,也是必须走个半圆的,特判了就行了。

代码如下:

#include <bits/stdc++.h>using namespace std;typedef long long LL;typedef pair<int,int> PII;const int MaxN = 200003;#define x0 xxxx#define y0 yyyy#define x1 xxxxx#define y1 yyyyy#define X first#define Y secondint x0,x1,y0,y1,n,cnt;#define M_PI 3.14159265358979323846const double len=M_PI*20,len2=M_PI*10,len4=M_PI*5;PII e[MaxN];int a[MaxN],mn[MaxN];int main() {    ios::sync_with_stdio(false);cin.tie(0);    cin >> x0 >> y0 >> x1 >> y1 >> n;    if (x0>x1) {swap(x0,x1);swap(y0,y1);}    cout << fixed << setprecision(15);    cnt=0;    for (int i=1;i<=n;++i) {        int x,y;        cin >> x >> y;        if (x<min(x0,x1) || x>max(x0,x1) || y<min(y0,y1) || y>max(y0,y1)) continue;        cnt++;        e[cnt].first=x,e[cnt].second=y;    }    if (x1==x0) {        double ans=(long long)abs(y1-y0)*100LL;        for (int i=1;i<=cnt;++i) if (e[cnt].X==x1) ans=ans-20LL+len2;        cout << ans << endl;        return 0;    }    if (y1==y0) {        double ans=(long long)abs(x1-x0)*100LL;        for (int i=1;i<=cnt;++i) if (e[cnt].Y==y1) ans=ans-20LL+len2;        cout << ans << endl;        return 0;    }    sort(e+1,e+cnt+1);    //if (x1<x0) reverse(e+1,e+cnt+1);    if (y1<y0) for (int i=1;i<=cnt;++i) e[i].Y=2LL*y0-e[i].Y;    for (int i=1;i<=cnt;++i) a[i]=e[i].Y;    for (int i=1;i<=cnt;++i) mn[i]=0x7fffffff;    mn[0]=0x80000000;    int sum=0;    for (int i=1;i<=cnt;++i) {        int x=lower_bound(mn,mn+cnt+1,a[i])-mn;        mn[x]=a[i];        sum=max(sum,x);    }    double ans=100LL*(abs(x0-x1)+abs(y0-y1));    ans=ans-20*sum+len4*sum;    if(sum==abs(x0-x1)+1||sum==abs(y0-y1)+1)        ans=ans+len4;    cout << ans << endl;    return 0;}

下面三题我都还没A掉..就先放着。。