Codeforces Round #608 (Div. 2) && Codeforces Round #607 (Div. 2)

Codeforces Round #607 (Div. 2)
A - Suffix Three

#include
using namespace std;
int main()
{
    string s;
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>s;
        if(s[s.size()-2]=='p'&&s[s.size()-1]=='o')
            cout<<"FILIPINO"<

B - Azamon Web Services
O(n^3)的做法加上小剪枝(stl的cmp有多快我不知道)

#include
using namespace std;
int T;
string s,t;
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>s>>t;
        if(st[i]) continue;
                swap(s[i],s[j]);
                if(s

C - Cut and Paste
题目转弯瞎说一大堆,其实就是把后面的一段复制来复制去,那么直接模拟即可

如果字符串的长度大于x了只有计数,否则在计数的同时把字符串加长。

#include
using namespace std;
typedef long long ll;
const int mod=1e9+7;
string s;
int main()
{
    int t;cin>>t;
    while(t--)
    {
        int x;
        cin>>x>>s;
        ll len=s.size(),bk=s.size();
        bool flag=false;
        for(int i=0;i=s.size()) break;
            if(!flag)
            {
                if(bk>0) bk--;
                string k=s.substr(i+1,bk);
                if(s[i]-'0'==2) s+=k;
                if(s[i]-'0'==3) s+=k+k;
                len=(len+bk*(s[i]-'0'-1))%mod;
                bk=bk*(s[i]-'0')%mod;
                if(len>x) flag=true;
            }
            else
            {
                if(bk>0) bk--;
                len=(len+bk*(s[i]-'0'-1))%mod;
                bk=bk*(s[i]-'0')%mod;
            }
        }
        printf("%lld\n",len);
    }
}

D - Beingawesomeism
答案只有0~4和无解几种可能,分类讨论:
无解:矩阵全为P
0次:矩阵全为A
1次:矩阵在边界一行或者一列全为A
2次:矩阵在四个顶点有一个A或者有某行某列全为A
3次:矩阵在边界有一个A
4次:矩阵中有A即可

#include
using namespace std;
const int N=77;
int n,m;
char s[N][N];
bool judge1()
{
    bool f1=true,f2=true,f3=true,f4=true;
    for(int i=1;i<=m;i++)
    {
        if(s[1][i]!='A') f1=false;
        if(s[n][i]!='A') f2=false;
    }
    for(int i=1;i<=n;i++)
    {
        if(s[i][1]!='A') f3=false;
        if(s[i][m]!='A') f4=false;
    }
    return f1|f2|f3|f4;
}
bool judge2()
{
    if(s[1][1]=='A'||s[1][m]=='A'||s[n][1]=='A'||s[n][m]=='A') return true;
    for(int i=1;i<=n;i++)
    {
        bool flag=true;
        for(int j=1;j<=m;j++)
        if(s[i][j]!='A') {flag=false;break;}
        if(flag) return true;
    }
    for(int j=1;j<=m;j++)
    {
        bool flag=true;
        for(int i=1;i<=n;i++)
            if(s[i][j]!='A'){flag=false;break;}
        if(flag) return true;
    }
    return false;
}
bool judge3()
{
    for(int i=1;i<=m;i++)
    {
        if(s[1][i]=='A') return true;
        if(s[n][i]=='A') return true;
    }
    for(int i=1;i<=n;i++)
    {
        if(s[i][1]=='A') return true;
        if(s[i][m]=='A') return true;
    }
    return false;
}
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%s",s[i]+1);
        int tot=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            if(s[i][j]=='P') tot++;
        if(tot==n*m) printf("MORTAL\n");
        else if(tot==0) printf("0\n");
        else if(judge1()) printf("1\n");
        else if(judge2()) printf("2\n");
        else if(judge3()) printf("3\n");
        else printf("4\n");;
    }
}

E - Jeremy Bearimy
从边的角度考虑,如果要使总和尽可能的大,就是要使得边被路径穿过的次数最大那么一条连接u,v边被选的次数就使max(si[u],si[v]),贡献的价值是max(si[u],si[v])*wi

再考虑小的,如果一条边两边的点数都为偶数,那么只有使边两边相互配对即可,这条边就不需要被选,而除此之外的边只能被迫选择,如果采用的方案足够优秀,是不会有边重合的,因此一次dfs即可。

#include
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll ans,res;
int k,tot,head[N],si[N],nex[N<<1],to[N<<1],wi[N<<1];
void add(int u,int v,int w){to[++tot]=v;nex[tot]=head[u];head[u]=tot;wi[tot]=w;}
void dfs(int u,int p)
{
    si[u]=1;
    for(int i=head[u];i;i=nex[i])
    {
        int v=to[i];if(v==p) continue;
        dfs(v,u);
        si[u]+=si[v];
        ans+=(ll)min(si[v],k-si[v])*wi[i];
        if(si[v]%2==0&&(k-si[v])%2==0) res-=wi[i];
    }
}
int main()
{
    int t;scanf("%d",&t);
    while(t--)
    {
        memset(head,0,sizeof(head));tot=0;
        scanf("%d",&k);
        k*=2;
        ans=res=0;
        for(int i=1;i

Codeforces Round #608 (Div. 2)
A - Suits

#include
using namespace std;
typedef long long ll;
int main()
{
    ll a,b,c,d,e,f;
    scanf("%lld%lld%lld%lld%lld%lld",&a,&b,&c,&d,&e,&f);
    int t=min(a,d);
    ll ans=0;
    for(int i=0;i<=t;i++)
        ans=max(ans,i*e+min(min(b,c),d-i)*f);
    cout<

B - Blocks
无论怎么翻,两种颜色的奇偶性不变,因此线性的从左到右翻过去

#include
using namespace std;
int n;
string s;
int main()
{
    cin>>n>>s;
    int ans1=0,ans2=0;
    for(int i=0;iq;
    for(int i=0;i

C - Shawarma Tent
对于一个点x,y,假设路径是sx,sy->sx,y->x,y,那么如果有另外一个点,如果走另外一个点不经过sx,sy->sx,y这条路,那么第二条路不会重合,反正很容易想到只要往sx,sy的上下左右四个方向加点就行

By Huah, contest: Codeforces Round #608 (Div. 2), problem: (C) Shawarma Tent, Accepted, #
 #include
using namespace std;
const int N=2e5+5;
int n,sx,sy;
struct node
{
    int x,y;
}a[N];
int ans1,ans2,ans3,ans4;
int main()
{
    scanf("%d%d%d",&n,&sx,&sy);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d",&a[i].x,&a[i].y);
        int x=a[i].x-sx,y=a[i].y-sy;
        if(y>0) ans1++;
        if(y<0) ans2++;
        if(x>0) ans3++;
        if(x<0) ans4++;
    }
    if(ans1>=ans2&&ans1>=ans3&&ans1>=ans4)
        printf("%d\n%d %d\n",ans1,sx,sy+1);
    else if(ans2>=ans1&&ans2>=ans3&&ans2>=ans4)
        printf("%d\n%d %d\n",ans2,sx,sy-1);
    else if(ans3>=ans1&&ans3>=ans2&&ans3>=ans4)
        printf("%d\n%d %d\n",ans3,sx+1,sy);
    else printf("%d\n%d %d\n",ans4,sx-1,sy);
}

D - Portals
首先倒推一个数组d[i],表示要想从这里跑到终点,那么至少要有d[i]的军力。然后想一想,如果在第i个港口,它在i+1~n的位置的时候也可以保护它,那么可以先不管它,到后面再保护也是一样的。那么就线性的去模拟,开一个优先队列,如果碰到一个在i位置可以保护,跑到后面就不能保护了,那么我只能选择保护这个港口了,当然和优先队列里面的比较,因为优先队列里的元素都是已经被保护的,但想一下,放弃前面一个小价值的城堡,保护后面一个价值更大的城堡,这样也是可以滴。

#include
using namespace std;
typedef long long ll;
const int N=5005;
int n,m,k,a[N],b[N],c[N],d[N];
vectorv[N];
bool vis[N];
int vv[N];
struct node
{
    int x,id;
    node(int x=0,int id=0):x(x),id(id){}
    bool operator<(const node&o)const
    {
        return x>o.x;
    }
};
priority_queueq;
pairp[N];
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++)
        scanf("%d%d%d",&a[i],&b[i],&c[i]);
    for(int i=1;i<=m;i++)
    {
        int x,y;scanf("%d%d",&x,&y);
        v[x].push_back(y);
        vv[y]++;
    }
    for(int i=1;i<=n;i++) vv[i]++;
    d[n]=a[n];
    for(int i=n-1;i>=1;i--)
        d[i]=max(a[i],d[i+1]-b[i]);
    if(k=0;j--)
            if(!vis[p[j].second])
            {
                if(now>d[i+1])
                {
                    now--;
                    q.push(node(p[j].first,p[j].second));
                    vis[p[j].second]=true;
                }
                else if(!q.empty())
                {
                    if(q.top().x

E Common Number
根据题意可以画出如图左边的一颗树,一个数的出现次数即为该结点以及该结点所有儿子结点的数量。

但是如图左边的树是不容易计算的,我们把数变一下形,转换成如图右边的二叉树,由于计算结点时出现多次的结点也只有一次的贡献

所以问题转换为在二叉树上进行计算,当要计算的数为x,如果x为奇数,就是普通二叉树上计算结点,如果x为偶数,显然计算的是x/2的结点数量减1。

Codeforces Round #608 (Div. 2) && Codeforces Round #607 (Div. 2)_第1张图片

#include
using namespace std;
typedef long long ll;
ll n,k;
ll cal(ll x)
{
    ll tot=1,ans=0;
    while(x*2<=n)
    {
        ans+=tot;
        x*=2;tot*=2;
    }
    ans+=min(tot,n-x+1);
    return ans;
}
int main()
{
    scanf("%lld%lld",&n,&k);
    ll l=1,r=n/2,ans=1;
    while(l<=r)
    {
        ll m=l+r>>1;
        if(cal(m)-1>=k) ans=max(ans,m*2),l=m+1;
        else r=m-1;
    }
    l=0,r=(n-1)/2;
    while(l<=r)
    {
        ll m=l+r>>1;
        if(cal(m*2+1)>=k) ans=max(ans,m*2+1),l=m+1;
        else r=m-1;
    }
    printf("%lld\n",ans);
}

你可能感兴趣的:(Codeforces Round #608 (Div. 2) && Codeforces Round #607 (Div. 2))