AtCoder Grand Contest 029 翻车记

  A:对于每个B,会和其右边的每个W交换一次。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
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;
ll ans=0;
char s[N];
int main()
{
    scanf("%s",s+1);n=strlen(s+1);
    int cnt=0;
    for (int i=n;i;i--)
    if (s[i]=='W') cnt++;
    else ans+=cnt;
    cout<<ans;
    return 0;
}
View Code

  B:从大到小贪心,遇到某个数能和其他数组成2的次幂就把他俩删掉。正确性基于这点:按从大到小的顺序找到的数,若能匹配,其在剩余的数中所能匹配的数是唯一的,这样匹配之后无论如何不会更劣。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
#define ll long long
#define N 200010
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;
map<int,int> cnt; 
int main()
{
    n=read();
    for (int i=1;i<=n;i++) cnt[a[i]=read()]++;
    sort(a+1,a+n+1);
    for (int i=n;i>=1;i--)
    if (cnt[a[i]])
    {
        int t=a[i];cnt[a[i]]--;
        while (t!=(t&-t)) t^=t&-t;
        if (cnt[(t<<1)-a[i]]) ans++,cnt[(t<<1)-a[i]]--;
        else cnt[a[i]]++;
    }
    cout<<ans;
    return 0;
}
View Code

  C:调了半天贪心一直过不掉,好长时间之后才发现假掉了,加个二分就过了,莫名其妙的花了50min。二分答案,维护一个栈存储字符串的非a位置,如果当前字符串比上个字符串长,显然后面全填上a就可以了;否则弹栈至非a位置不大于当前串长度,然后将末尾达到限制的位置弹出,如果弹空了说明不合法(当然如果有剩余的a是合法的),否则将未达限制的最后一位+1,后面全清成a即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define N 200010
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],pos[N],num[N],top,ans;
bool check(int ans)
{
    top=0;
    for (int i=2;i<=n;i++)
    if (a[i]<=a[i-1])
    {
        int x=a[i];
        while (top&&pos[top]>x) top--;
        while (top&&pos[top]==x&&num[top]==ans) top--,x--;
        if (x==0) return 0;
        else if (pos[top]<x) {pos[++top]=x,num[top]=2;if (ans==1) return 0;}
        else num[top]++;
    }
    return 1;
}
int main()
{
    n=read();
    for (int i=1;i<=n;i++) a[i]=read();
    int l=1,r=n;
    while (l<=r)
    {
        int mid=l+r>>1;
        if (check(mid)) ans=mid,r=mid-1;
        else l=mid+1;
    }
    cout<<ans;
    return 0;
}
View Code

  D:显然第一个人每次都是必须走的。每进入某一列,第二个人都可以选择一直不动,直到第一个人的移动使其撞到障碍。如果可以到达(x,y),则对(x,1..y-1),要么可以到达,要么在x之前有障碍。那么让一颗棋子从起点出发,每次都尽量移动,set找一下该列最近障碍,对每一列的答案取个min即可。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
using namespace std;
#define ll long long
#define N 200010
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 r,c,n,t,x,y,ans;
map<int,int> f[N];
set<int> g[N];
struct data{int x,y;
}a[N];
int main()
{
    r=read(),c=read();n=read();ans=r+1;
    for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),f[a[i].x][a[i].y]=1,g[a[i].y].insert(a[i].x);
    for (int i=1;i<=c;i++) g[i].insert(r+1);
    int x=1,y=1;
    for (;x<r;)
    {
        ans=min(ans,*g[y].lower_bound(x));
        x++;if (!f[x][y+1]&&y<c) y++;
    }
    ans=min(ans,*g[y].lower_bound(x));
    cout<<ans-1;
    return 0;
}
View Code

  死于罚时。result:rank 110 rating +389

原文地址:https://www.cnblogs.com/Gloid/p/10125171.html