【浮*光】【Codeforces Round #484 (Div. 2)】解题报告

A.Row

#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;
}

B. Bus of Characters

#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;  
}

C. Cut 'em all!

#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;  
}  

D. Shark

#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

E. Billiard


F. The Meeting Place Cannot Be Changed





                                                                                ——时间划过风的轨迹,那个少年,还在等你。

猜你喜欢

转载自blog.csdn.net/flora715/article/details/80583036