| 题目 | 难度 | 知识点 |
|---|---|---|
| A 小紫的均势博弈 | ★ | 签到 |
| B 小紫的劣势博弈 | ★ | 签到 |
| C 小紫的01串操作 | ★ | 思维 |
| D 小紫的优势博弈 | ★ | 思维 |
| E 小紫的线段染色 | ★ | 贪心 |
| F 小紫的树上染色 | ★★ | 二分/树 |
怎么人均会F,确实没想到二分直接放弃了,看题解搞二分但是居然不会写。后来才发现这么简单。呃呃呃属实太菜了。
小紫的均势博弈
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int main(void)
{
int n; cin>>n;
if(n&1) puts("kou");
else puts("yukari");
return 0;
}
小紫的劣势博弈
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long int LL;
LL a[N];
int main(void)
{
int n; cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
sort(a,a+n);
LL sum=0;
for(int i=0;i<n;i++){
if(i&1) sum-=a[i];
else sum+=a[i];
}
cout<<sum;
return 0;
}
小紫的01串操作
不会剪短写法,就写了个暴力,但是可以看到优化后的字符串长度过大一定无解,故只需判断一个很小的长度就行了。
#include<bits/stdc++.h>
using namespace std;
void solve()
{
string s; cin>>s;
vector<char>ve;
int n=s.size();
for(int i=0;i<n;i++)
{
int j=i;
while(j+1<n&&s[j+1]==s[i]) j++;
i=j;
ve.push_back(s[i]);
}
int flag=0;
if(ve.size()<=3) flag=1;
else if(ve.size()>3&&ve.size()<=10)
{
for(int i=0;i<ve.size();i++)
{
vector<char>temp;
temp=ve;
if(ve[i]=='0')
{
temp[i]='1';
int cnt=0;
for(int j=0;j<ve.size();j++)
{
int k=j;
while(k+1<ve.size()&&temp[k+1]==temp[j]) k++;
j=k;
cnt++;
}
if(cnt<=3) flag=1;
}
if(ve[i]=='1')
{
temp[i]='0';
int cnt=0;
for(int j=0;j<ve.size();j++)
{
int k=j;
while(k+1<ve.size()&&temp[k+1]==temp[j]) k++;
j=k;
cnt++;
}
if(cnt<=3) flag=1;
}
}
}
if(flag) puts("Yes");
else puts("No");
}
int main(void)
{
int t; cin>>t;
while(t--) solve();
return 0;
}
将润色后的字符串如果长度小于等于5必可以,这个可以试一下发现是一定的。
#include<bits/stdc++.h>
using namespace std;
int main(void)
{
int t; cin>>t;
while(t--)
{
string s; cin>>s;
int cnt=0;
for(int i=0;i<s.size();i++)
{
int j=i;
while(j+1<s.size()&&s[j+1]==s[i]) j++;
i=j;
cnt++;
}
if(cnt<=5) puts("Yes");
else puts("No");
}
return 0;
}
小紫的优势博弈
暴力模拟即可,时间复杂度是线性的。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int s0[N],s1[N];
int main(void)
{
int n; cin>>n;
string s; cin>>s;
s="_"+s;
for(int i=1;i<=n;i++)
{
s0[i]=s0[i-1];
s1[i]=s1[i-1];
if(s[i]=='0') s0[i]++;
if(s[i]=='1') s1[i]++;
}
int ans=0;
for(int i=1;i<=n;i++)
{
int j=i+1,cnt0=0,cnt1=0;
while(j<=n)
{
if(s[j]=='1') cnt1++;
else if(s[j]=='0') cnt0++;
if( cnt0%2==0 && cnt1%2==0 &&(cnt0 || cnt1))
{
ans++;
break;
}
j++;
}
}
printf("%.10lf",ans*1.0/n);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int cnt0[N],cnt1[N];
int main(void)
{
int n; cin>>n;
string s; cin>>s;
s=" "+s;
for(int i=1;i<=n;i++)
{
cnt0[i]=cnt0[i-1]+(s[i]=='0');
cnt1[i]=cnt1[i-1]+(s[i]=='1');
}
map<pair<int,int>,int>last_pos;
int ans=0;
for(int i=1;i<=n;i++)
{
last_pos[{cnt0[i]%2,cnt1[i]%2}]=i;
}
for(int i=1;i<=n;i++)
{
int j=last_pos[{cnt0[i]%2,cnt1[i]%2}];
if(j>i) ans++;
}
printf("%.8lf",ans*1.0/n);
return 0;
}
小紫的线段染色
说实话不会,纯猜的要么左端点排,要么右端点排。想的右端点但是歪了。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node
{
int l,r,id;
};
bool cmp(node a,node b)
{
return a.l<b.l;
}
vector< node >ve;
int st[N];
int main(void)
{
int n; cin>>n;
for(int i=0;i<n;i++)
{
int l,r; cin>>l>>r;
ve.push_back({l,r,i+1});
}
sort(ve.begin(),ve.end(),cmp);
if(n==1)
{
cout<<1<<'\n'<<ve[0].id;
}else
{
memset(st,-1,sizeof st);
vector<int>red,green; red.push_back(ve[0].r);
green.push_back(ve[1].r);
vector<int>ans; ans.push_back(ve[1].id);
for(int i=2;i<n;i++)
{
if(ve[i].l>red.back() && red.back()<=green.back() ) red.push_back(ve[i].r);
else if(ve[i].l>green.back()) green.push_back(ve[i].r),ans.push_back(ve[i].id);
else
{
cout<<-1;
return 0;
}
}
cout<<ans.size()<<endl;
for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
}
return 0;
}
小紫的树上染色
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
vector<int>ve[N];
int dp[N],n,k,cnt;
void dfs(int u,int fa,int x)
{
dp[u]=1;
for(int i=0;i<ve[u].size();i++)
{
int j=ve[u][i];
if(j==fa) continue;
dfs(j,u,x);
dp[u]+=dp[j];
}
if(dp[u]>x)
{
cnt++;
dp[u]=0;
}
}
int check(int x)
{
cnt=0;
for(int i=0;i<=n;i++) dp[i]=0;
dfs(1,0,x);
return cnt;
}
int main(void)
{
cin>>n>>k;
for(int i=1;i<=n-1;i++)
{
int a,b; cin>>a>>b;
ve[a].push_back(b);
ve[b].push_back(a);
}
int l=0,r=n;
while(l<r)
{
int mid=(l+r)/2;
if(check(mid)<=k) r=mid;
else l=mid+1;
}
cout<<l;
return 0;
}