A:题目链接:点击打开链接
题目大意:给一些01串,满足俩条件:(1)两个1不能相邻;(2)这个子串在不打破上述条件的情况下,不能再放1了。
题目思路:
第一种就是纯模拟,如果有两个相邻的1,或者出现有三个相邻的0(头尾只需两个),则输出“NO”。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 20005;
char s[maxn];
int n;
int main()
{
cin>>n;
scanf("%s",s);
bool flag = 1;
int tot = 0;
for(int i=0;i<n;i++)
{
if(s[i]=='1'&&(s[i+1]=='1'||s[i-1]=='1'))
{
flag = false;
break;
}
if(s[i]=='0'&&(i==0||s[i-1]=='0')&&(i==n-1||s[i+1]=='0'))
{
flag = false;
break;
}
}
if(!flag) {
cout<<"No"<<endl;
}
else
cout<<"Yes"<<endl;
return 0;
}
第二种:
在头尾各加上一个0,如果出现三个连续的0或者两个连续的1则输出“No”。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
int n;
string s;
int main()
{
cin>>n>>s;
s = '0'+s+'0';
int tot = 0;
bool flag = 1;
for(int i=0;i<=n;i++)
{
if(s[i]=='1') {
if(i>0&&s[i]==s[i-1]) {
flag = 0;
break;
}
tot = 0;
}
else {
tot++;
if(tot>=3) {
flag = false;
break;
}
}
}
if(!flag) {
cout<<"No"<<endl;
}
else
cout<<"Yes"<<endl;
return 0;
}
------------------------------------------------分割线--------------------------------------------------------------------
B题:题目链接:点击打开链接
题目大意:
有辆公交车,共有n排,每排有2个座位,其中第i排座位的宽度均为Wi。
现在上来2*n个旅客,他们分为两种:
(1)只坐一排两个位置都空的位置,并且选一个(wi)最小的坐;
(2)只坐一排另一个人的旁边(一空一有人),并且选大的坐。
思路,首先用一个结构体从小到大排个序。然后如果上来的是第一类人,就把它这个位置加入优先队列中;如果上来的是第二类人,就把优先队列顶部的座位给他坐,并pop出去- -就完成惹。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
typedef long long ll;
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
int n,w[maxn],vis[maxn];
char s[maxn*2];
pair<ll,int> a[maxn*2];
vector<pair<ll,int> >e;
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
{
int x;
scanf("%d",&x);
pair<ll,int> p;
p.first = x;
p.second = i+1;
e.push_back(p);
}
scanf("%s",s);
sort(e.begin(),e.end());
priority_queue<pair<ll,int> > q;
memset(vis,0,sizeof(vis));
int cnt = 0;
for(int i=0;i<n*2;i++)
{
if(s[i]=='0')
{
q.push(e[cnt]);
// cout<<q.size()<<endl;
cout<<e[cnt].second<<" ";
cnt++;
}
else {
cout<<q.top().second<<" ";
q.pop();
}
}
return 0;
}
------------------------------------------------分割线--------------------------------------------------------------------
C题目链接:点击打开链接
题目大意:
给一个树(看好了是 树 ),问最多能删除几条边,使整个图所有的联通的部分都拥有偶数个节点。(我也不知道什么叫相同的尺寸,估计是所有节点和其边组成的图长的都一样)
题目思路:
如果节点数是奇数,直接输出-1,因为这不符合常识,请问如何用3个节点组成2个一模一样的树?
首先以节点1为根节点,统计出所有节点包含的子节点数量。如果该节点的儿子是奇数个,那么ans++;到了最后要记得ans-1,因为和根节点连着的边是不能去掉的,这辈子都不能去掉的。
这题的话,我建议自己模拟一下。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 200005;
vector<int> e[maxn];
int n,k,num[maxn];
bool vis[maxn];
int dfs(int x)
{
vis[x] = 1;
for(int i=0;i<e[x].size();i++)
{
if(!vis[e[x][i]])
{
num[x]++;
num[x] += dfs(e[x][i]);
}
}
return num[x];
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
if(n%2) {
cout<<-1<<endl;
return 0;
}
num[1] = dfs(1);
int ans = 0;
for(auto i=1;i<=n;i++)
{
if(num[i]%2)
ans++;
}
cout<<ans-1<<endl;
return 0;
}