#include <bits/stdc++.h> using namespace std; /*【Row】 你有一排椅子。 如果以下两个条件成立,我们称之为“最大”的人员座位: 1.两边都没有人。2.不可能再多一个人。 座位由一个由0和1组成的字符串给出(0表示相应的座位是空的,1-占用的)。 目标是确定这次排的座位是否“最大”。第一个和最后一个座位不相邻(如果n≠2)。 n是椅子的数量。一串n个字符,每个字符都是0或1,描述座位。 如果座位是“最大”,输出“是”, 否则,打印“否”。 */ //【分析】在头尾各加一个0,出现三个连续0或者两个连续1则输出“No”。*/ int n; string ss; int main(){ scanf("%d",&n); cin>>ss; ss='0'+ss+'0'; //stl字符串的方便性qaq int now0=0; bool okk=true; for(int i=0;i<=n+1;i++){ //原串从0开始,且注意添加了字符 if(ss[i]=='1'){ if(i>0&&ss[i]==ss[i-1]){ okk=false; break; } now0=0; } else{ now0++; if(now0==3){ okk=false; break; } } } if(!okk) cout<<"No"<<endl; else cout<<"Yes"<<endl; return 0; }
#include <bits/stdc++.h> using namespace std; /*【B. Bus of Characters】 有n排座位,每排都有2个座位。第i行中两个座位的宽度均为wi厘米。 所有的整数都是不同的。公共汽车最初是空的。每个2n站有一位乘客进入巴士。 有两种类型的乘客: 1.内向者总是选择两个座位都空的,并选择宽度最小的一排其中一个座位; 2.外向者总是选择(内向)占据一个座位的位置,选择了座位宽度最大的。 请确定每位乘客将乘坐哪一排。'0'->内向的。'1'->外向的。 保证外向者等于内向者的数量(两个数字等于n)。 */ // 分析:先给wi排序。让内向者入优先队列,外向者与顶部元素一起pop。 // 提示:使用pair数组的first & second,方便储存 typedef long long ll; const int maxn = 200005; pair<ll,int> a[maxn*2]; vector<pair<ll,int> >e; //用于记录w状态 int vis[maxn]; int main(){ int n; scanf("%d",&n); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); pair<ll,int> p; p.first=x; p.second=i; //存入编号 e.push_back(p); } sort(e.begin(),e.end()); //pair类型排序,x优先 string s; cin>>s; priority_queue<pair<ll,int> > q; //pair类型优先队列 int cnt=0; //便于计数 for(int i=0;i<n*2;i++){ //开始上车 if(s[i]=='0'){ //内向 q.push(e[cnt]); //“排”的结构体存入q中,方便对应列寻找 cout<<e[cnt].second<<" "; //输出排数的编号 cnt++; //“排”个数增加 } else{ //外向 cout<<q.top().second<<" "; q.pop(); //出队 } } return 0; }
#include <bits/stdc++.h> using namespace std; /*【C. Cut 'em all!】 给一个树,问最多能删除几条边,使整个图所有相联通的部分都拥有偶数个节点。*/ /*【分析】 如果节点数是奇数,直接输出-1。首先以节点1为根节点,统计出{所有节点包含的子节点数量}。 如果该节点的儿子是奇数个,那么ans++;到了最后要记得ans-1,因为和根节点连着的边是不能去掉的。 */ 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!=0){ cout<<-1<<endl; return 0; } //n为奇数 num[1]=dfs(1); int ans=0; for(int i=1;i<=n;i++) if(num[i]%2) ans++; //此边要删去 cout<<ans-1<<endl; return 0; }
#include <bits/stdc++.h> using namespace std; /*【D. Shark】 鲨鱼每天游ai公里,如果它一天游的距离大于等于k,我们就认为它游到了一个新的地方; 否则认为它这一天停留在原来的地方。这只鲨鱼到过的地方不会重复。 现在给出它n天游的距离(每天都不相等),我们要求出一个k,满足: 1.鲨鱼停留在每个地方的天数相等。(一天游的距离大于等于k时不算停留)。 2.停留过的地方尽可能多。 3.有多个解时k取最小值。 */ /* 分析》确定一个k,使得[小于k的子序列长度都是相等的],而且要尽可能多,最后k取最小值。 根据第三个限制,我们可以想到[最后的解一定是其中一个a的值加一]。 基于每个a都不相同这个条件我们可以对a先递增排序,顺序处理的时候因为是从小到大, 所以每次只需要增加一个满足条件的点即可。把这个点的标记置为1,分别判断它的左右是否标记过, 如果标记过就连成一个区间。至于怎么判断每个区间是否相等,我们可以维护一个最大区间的长度, 和所有区间的长度,我们还知道区间数量,所以有 最大长度*区间数量=总长度。 通过这个公式就可以判断是否区间长度都相等。 */ typedef long long ll; const int inf = 0x3f3f3f3f; const int mod = 1000000009; const int maxn = 100005; map<int, int> mp; int a[maxn], l[maxn], r[maxn]; bool vis[maxn]; int main(){ int n; scanf("%d",&n); for (int i=1;i<=n;++i){ scanf("%d",&a[i]); mp[a[i]]=i;//map记录每个值原来的位置 } sort(a+1,a+n+1); memset(vis,0,sizeof(vis)); int len=0,ans=0,p=a[n-1]+1,cnt=0; for(int i=1;i<=n;++i) { int pos=mp[a[i]]; vis[pos]=1; if(vis[pos-1]==1&&vis[pos+1]==1){ //左右都标记过,就连成一片 --cnt; r[l[pos-1]]=r[pos+1];//更新区间范围 l[r[pos+1]]=l[pos-1];//更新区间范围 r[pos]=r[pos+1]; l[pos]=l[pos-1]; } else if(vis[pos-1]==1){ //左边标记过 l[pos]=l[pos-1]; r[pos]=pos; r[l[pos-1]]=pos; } else if(vis[pos+1]==1){ //右边标记过 r[pos]=r[pos+1]; l[pos]=pos; l[r[pos+1]]=pos; } else{ //产生一个新的区间 ++cnt; l[pos]=pos; r[pos]=pos; } int ll=r[pos]-l[pos]+1; if(ll>len) len=ll; if(len*cnt==i) //是否每个区间长度都相等 if(cnt>ans){ ans=cnt; p=a[i]+1; } } printf("%d\n", p); return 0; } //来自https://blog.csdn.net/hcx11333/article/details/80387199 感谢dalao
F. The Meeting Place Cannot Be Changed