今晚看完电影再回来补(到宿舍11点半了所以会写的简便点)
A.首先手玩一下
2的时候稳后手赢
3:1 2 和3都是后手赢
4:变成1 1 2或者1 3都是后手赢
5:直接1 4| | 1 1 3| |1 1 1 2 找到了 1 1 3先手能赢
好了后面不用找了,先手直接全部变成 1 1 x就行
所以n<=4bob赢,否则 alice赢
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include<functional>
using namespace std;
const int N = 2e5+10;
typedef pair<int, int> PII;
int n,m,k;
PII a[N];
int f[N];
void solve()
{
cin>>n;
if(n<=4) cout<<"Bob\n";
else cout<<"Alice\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
B.手玩一下添加的数要一直非递减,如果遇到一个转折点,要判断是不是小于开头(开头是前面最小的),然后后面就要继续在这个转折点后递增且小于等于开头的数
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include<functional>
using namespace std;
const int N = 2e5+10;
int n,m,k;
void solve(){
cin>>n;
bool f=false;
vector<int> a;
for(int i=1;i<=n;i++){
int x;cin>>x;
if(a.empty()||(f==false&&x>=a.back())){
cout<<"1";
a.push_back(x);
}
else if(f==false&&x<a.back())
{
if(x<=a[0]){
cout<<"1";
f=true;
a.push_back(x);
}
else cout<<"0";
}
else if(f==true)
{
if(x>=a.back()&&x<=a[0]){
cout<<1;a.push_back(x);
}
else cout<<0;
}
}
cout<<"\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
C.常规套路是枚举换成哪个字符的
然后就要想一些性质了
比如dcbbbcaddddc
把c变小,第一个c影响了前面小于他的点,但是后面还有c所以等于没改变结果,中间的点c影响了前面比它小的点,但后面又有个c所以不改变前面的点也等于没改变结果,最后一个点c变小,前面小于c的点是全部改变的,所以改最后一个点才有影响
把c变大,其实这里可以直观的想,变大了希望前面受到影响最小,让前面尽可能的正数,最好是放在最左边的c
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include<functional>
using namespace std;
const int N = 2e5+10;
int n,m,k;
int w[N];
int ch[N][26];
void init(){
w[0]=1;
for(int i=1;i<=5;i++)
w[i]=w[i-1]*10;
}
void solve()
{
string s;
cin>>s;
n=s.size();
s="?"+s;
vector<vector<int>> pos(5);
for(int i=1;i<=n;i++)
pos[s[i]-'A'].push_back(i);
function<long long(string)> get=[&](string s)->long long{
int mx=0;
long long cnt=0;
for(int i=n;i>=1;i--){
if(s[i]-'A'<mx) cnt-=w[s[i]-'A'];
else cnt+=w[s[i]-'A'];
mx=max(mx,s[i]-'A');
}
return cnt;
};
long long res=get(s);
for(int i=0;i<5;i++){
for(int j=0;j<5;j++)
{
if(pos[i].empty()) continue;
s[pos[i].back()]=char(j+'A');
res=max(res,get(s));
s[pos[i].back()]=char(i+'A');
s[pos[i][0]]=char(j+'A');
res=max(res,get(s));
s[pos[i][0]]=char(i+'A');
}
}
cout<<res<<"\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
init();
cin>>t;
while(t--) solve();
}
D.分成k/2对,且要每对有交集,和其他没交集,等于两个交集的在一起,且其他和这两个没交集
直接dp即可
首先按照右端点排序(左端点会wa),因为如果按照左端点排序,如果这个区间很长,但是左端点很小,只能和前面的端点结合,但是它其实还能和被自己包含的区间结合的
然后dp即可
状态:前完了前i-1个区间能组成k/2对,且以i为最后一对的第二个区间的最大值
直接dp,说明这里可以预处理或者直接二分降低
第一个朴素版方便读者看懂状态转移
第二个优化的
这两个都能ac
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include<functional>
using namespace std;
const int N = 2e5+10;
typedef pair<int, int> PII;
int n,m,k;
PII a[N];
int f[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second,f[i]=0;
//vector<int> f(n+1,0);
sort(a+1,a+1+n,[&](const PII p,const PII q){
return p.second<q.second;
});
for(int i=2;i<=n;i++)
{
f[i]=max(f[i-1],f[i]);
for(int j=1;j<i;j++)
{
if(a[i].first<=a[j].second)
{
for(int k=1;k<j;k++)
{
if(a[k].second<min(a[i].first,a[j].first))
{
f[i]=max(f[i],f[k]+2);
}
}
f[i]=max(f[i],2);
}
}
}
cout<<n-*max_element(f+1,f+1+n)<<"\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include<functional>
using namespace std;
const int N = 2e5+10;
typedef pair<int, int> PII;
int n,m,k;
PII a[N];
int f[N];
void solve()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].first>>a[i].second,f[i]=0;
//vector<int> f(n+1,0);
sort(a+1,a+1+n,[&](const PII p,const PII q){
return p.second<q.second;
});
for(int i=2;i<=n;i++)
{
f[i]=max(f[i-1],f[i]);
for(int j=1;j<i;j++)
{
if(a[i].first<=a[j].second)
{
int l=1,r=j-1;
while(l<r){
int mid=l+r+1>>1;
if(a[mid].second<min(a[i].first,a[j].first)) l=mid;
else r=mid-1;
}
f[i]=max({f[i],f[0]+2,f[l]+2});
}
}
}
cout<<n-f[n]<<"\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
E.
首先可以贪心的让连续的空格尽可能长
OOOXOOOO
OOXOOOOO
如果能放5个
可以直接放连续5个O第二那里,贡献是4,如果放在第一行右边4个左边一个贡献3
右边3个左边两个贡献3
可以手完一下,连续的空格尽可能长是最优的
可以直接统计有多少个长度为x的连续O字串
然后直接从长度大的遍历到小的就行l
然后就有下面的代码
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include<functional>
using namespace std;
const int N = 2e5+10;
typedef pair<int, int> PII;
#define int long long
int n,m,k;
int a[N];
void solve()
{
cin>>n;
vector<vector<int>> g(n+1,vector<int>(n+1,0));
for(int i=1;i<=n;i++){
int x;cin>>x;
for(int j=1;j<=x;j++)
g[j][i]=1;
}
vector<int> cnt(n+1,0);
cin>>m;
for(int i=1;i<=n;i++)
{
int now=0;
for(int j=1;j<=n;j++){
if(g[i][j]==1){
cnt[now]++;now=0;
}
else now++;
}
cnt[now]++;
}
int res=0;
for(int i=n;i>=2;i--)
{
int t=min(cnt[i],m/i);
res+=t*(i-1);
cnt[i-1]+=cnt[i]-t;
m-=t*i;
}
cout<<res<<"\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}
然后就tle或者mle了
优化
从n开始倒叙枚举,用set记录哪一行后面行已经有有X了,因为X是直接前x行都有X的,只要记录后面最早有就行了,这样前面行肯定就有
举个例子把
XOOXOX
XOOXOX
XOOOOX
XOOOOO
后面的行已经存在的,前面行也一定存在
这里设置左右边界就简单很多
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include<functional>
using namespace std;
const int N = 2e5+10;
#define int long long
typedef pair<int, int> PII;
int n,m,k;
int a[N];
void solve()
{
cin>>n;
vector<int> cnt(n+1);
vector<int> tim(n+2);
vector<vector<int>> pos(n+1);
for(int i=1;i<=n;i++){
int x;cin>>x;
pos[x].push_back(i);
}
cin>>m;
set<int> s;
s.insert(0);s.insert(n+1);
tim[0]=tim[n+1]=n;
for(int i=n;i>=0;i--){
for(auto&x:pos[i]){
auto it=s.lower_bound(x);
int pre=*prev(it);
int nxt=*it;
int from=min(tim[pre],tim[nxt]);
cnt[nxt-pre-1]+=from-i;
s.insert(x);
tim[x]=i;
}
}
int ans=0;
for(int i=n;i>=1;i--)
{
int t=min(cnt[i],m/i);
ans+=t*(i-1);
cnt[i]-=t;
cnt[i-1]+=cnt[i];
m-=t*i;
}
cout<<ans<<"\n";
}
signed main(){
cin.tie(0);cout.tie(0);ios::sync_with_stdio(0);
int t=1;
cin>>t;
while(t--) solve();
}