Atcoder Grand Contest 019 总结

这把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
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<return 0;
}

B - Reverse and Compare

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

代码如下:

#include
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;ifor(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;i1)-cnt[s[i]-'a'][i+1];
    cout<return 0;
}

C - Fountain Walk

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

代码如下:


#include 
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 second
int x0,x1,y0,y1,n,cnt;
#define M_PI 3.14159265358979323846
const 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 (xmax(x0,x1) || ymax(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
    if (y1for (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掉..就先放着。。

你可能感兴趣的:(闲谈)