Codeforces Round #724 (Div. 2)(CD)

C. Diluc and Kaeya

题目大意:对于只含DK的字符串,求所有前缀的最大划分(划分后分成最多子串),划分后的每段字符串里DK的数量比例要相同。

思路:dp

设前i个数有x个D,y个K,则有d(x,y) = d(x/gcd(x,y) , y/gcd(x,y)) + 1,每对(x,y)去前面找前面已经出现过的比例,我们可以用map存(x,y),则只要map(x/gcd(x,y) , y/gcd(x,y))++即可

(其实unorder_map即可,不过要重载等号)

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pb push_back
#define IOS ios::sync_with_stdio(false)
#define int long long
#define inf 0x3f3f3f3f
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
#define endl "\n"
#define sf scanf
typedef long long ll;
const int N=5e5+10;

int n;
char s[N];
map <pair<int ,int > ,int > mp;
ll gcd(ll a ,ll b)
{
    while( b )
    {
        int t= a;
        a=b;
        b=t%b;
    }
    return a;
}
void solve()
{
    mp.clear();
    int x=0,y=0;
    _for(i,1,n)
    {
        if( s[i] == 'D') x++;
        else y++;
        cout<<++mp[{x/gcd(x,y),y/gcd(x,y)}]<<" ";
    }
    cout<<endl;

}
signed main()
{
    ///!!!
//    freopen("data.txt","r",stdin);
    //!!!
    IOS;
    int T;cin>>T;
    while( T-- )
    {
        cin>>n;_for(i,1,n) cin>>s[i];
        solve();
    }
}

D. Omkar and Medians

题目大意:给n个数,组成数组b,bi为a1,a2,a3....a_{2*i-1}的中位数,按照输入顺序去构造数组a,问是否存在这样的数组a。

对于每次加入一个bi,前一个中位数b_{i-1}要么向左移动一位,要么向右移动一位,在数组a中,我们设b_{i-1}左边第一个数为l , 右边第一个数为r,那么加入的bi需要在[l , r ]内,否则bi-1不能在左右一格的范围内移动(bi既要在数组a中间,又要让bi-1在bi旁边嘛)

用map迭代器可以快速找到上一个数,以及它左右两边的数,对于若左边没数则 l 赋值为负无穷,右边同理。

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <map>
#include <unordered_map>
#include <vector>
#include <queue>
using namespace std;
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
#define mst(v,s) memset(v,s,sizeof(v))
#define pb push_back
#define IOS ios::sync_with_stdio(false)
#define int long long
#define inf 0x3f3f3f3f
#define lson p<<1,l,mid
#define rson p<<1|1,mid+1,r
#define ls p<<1
#define rs p<<1|1
#define endl "\n"
#define sf scanf
#define fi first
#define se second
typedef long long ll;
const int N=2e5+10;
int a[N];
int n;
map <int ,int > mp;
bool solve()
{
    mp.clear();
    mp[a[1]]=1;//第一个数放入mp
    map < int ,int > ::iterator it;
    int l,r;//左右界
    _for(i,2,n)
    {
        it = mp.find(a[i-1]);//上一个数
        if( it == mp.begin() ) l = -inf;//上一个数左边没数,赋值为负无穷
        else l = (--it)->fi;//有数,赋值为左边的数
        it = mp.find(a[i-1]);
        if( (++it) == mp.end() ) r = inf;//同理
        else r = it->fi;//it已经++了
        mp[a[i]]=1;//当前的ai加入mp
        if( l<= a[i] && a[i] <= r)//判断是否在左右界内
        {
            continue;
        }
        return false;
    }
    return true;
}
signed main()
{
    ///!!!
//    freopen("data.txt","r",stdin);
    //!!!
    IOS;
    int T;cin>>T;
    while( T-- )
    {
        cin>>n;
        _for(i,1,n) cin>>a[i];
        if( n==1 )//一个数特判
        {
            cout<<"YES"<<endl;
            continue;
        }
        if( solve() ) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值