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,问是否存在这样的数组a。
对于每次加入一个bi,前一个中位数要么向左移动一位,要么向右移动一位,在数组a中,我们设
左边第一个数为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;
}
}