Codeforces Round #603 (Div. 2)

Codeforces Round #603 (Div. 2)

A. Sweet Problem

题意:多组数据,每组数据给出3种颜色的糖果,规定每天吃2颗糖果,颜色不能相同,问最多吃几天。

思路:3种糖果按照个数多少排序得到a≤b≤c,①若a+b≤c,则每天吃 c 和 a,b中的一种,可以吃a+b天。②若a+b>c,则先吃a和c让c和b一样多,然后若剩余的a为偶数则所有糖可以都吃完,若为奇数则最后会剩余1颗,所以此种情况对应天数为(a+b+c)/2天。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    long long n;
    long long num[3];
    cin>>n;
    while(n--){
        cin>>num[0]>>num[1]>>num[2];
        sort(num,num+3);
        if(num[0]+num[1]<=num[2]){
            cout<<num[0]+num[1]<<endl;
        }else{
            cout<<(num[0]+num[1]+num[2])/2<<endl;
        }
    }
    return 0;
}
View Code

B. PIN Codes

题意:多组数据,每组数据给出n个4位密码,现在要让给出的密码两两不相同,且每次只能更改一个密码的1位,问至少修改多少次并按顺序输出更改后的所有密码。

思路:因为n最大为10,所以密码修改可以只考虑1位,可以先把所有的pin code都放入一个unordered_map中并统计相应的个数,然后将重复的pin code最后一位进行更改找到没出现过的即可。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    string shuru[20];
    while(t--){
        int n,ans=0;
        unordered_map<string,int>tree;
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>shuru[i];
            if(tree.find(shuru[i])==tree.end()){
                tree[shuru[i]]=1;
            }else{
                tree[shuru[i]]++;
            }
        }
        for(auto i=tree.begin();i!=tree.end();i++){
            ans+=(*i).second-1;
        }
        cout<<ans<<endl;
        for(int i=1;i<=n;i++){
            if(tree[shuru[i]]>1){
                string s=shuru[i];
                for(int j=0;j<=9;j++){
                    s[3]=j+'0';
                    if(tree.find(s)==tree.end()){
                        tree[s]=1;
                        cout<<s<<endl;
                        tree[shuru[i]]--;
                        break;
                    }
                }
            }else{
                cout<<shuru[i]<<endl;
            }
        }
    }
    return 0;
}
View Code

C. Everyone is a Winner!

题意:多组数据,每组数据给出一个分值n,定义每个人的得分为n除以人数k(向下取整),问一共有多少种不同的分数。

思路:对于给定的n,i 从1循环到√n,(n/i) 和 (n/(n/i)) 是不同的分数,最后把0加上即可。

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--){
        long long n;
        set<long long>tree;
        cin>>n;
        for(long long i=1;i*i<=n;i++){
            long long ans=n/i;
            if(tree.find(ans)==tree.end()){
                tree.insert(ans);
                tree.insert(n/ans);
            }
        }
        tree.insert(0);
        cout<<tree.size()<<endl;
        for(auto i=tree.begin();i!=tree.end();i++){
            cout<<(*i)<<" ";
        }
        cout<<endl;
    }
    return 0;
}
View Code

D. Secret Passwords

题意:有n个密码,每个密码都是由小写字母则称,现在给密码分类,有2个标准。

· 若 密码a 和 密码b 都含有某个相同的字母,则a和b同类

· 若 密码a 和 密码c 同类,密码b 和 密码c 同类,则 密码a 和 密码b 同类。

问有几种不同类型的密码。

思路:并查集,依次将所有含有字母a的密码视为一个集团,merge在一起。再将含有字母b的密码视为一个集团,merge在一起……以此类推到字母z。最后查询有几个不同的集团即可。

#include<bits/stdc++.h>
using namespace std;
int father[200005];
vector<vector<int> >vec(27);
 
void init(int n){
    for(int i=1;i<=n;i++){
        father[i]=i;
    }
    return;
}
 
int getfather(int x){
    if(father[x]==x) return x;
    else return father[x]=getfather(father[x]);
}
 
void merge(int x,int y){
    int xx=getfather(x);
    int yy=getfather(y);
    if(xx<yy){
        father[xx]=yy;
    }else{
        father[yy]=xx;
    }
}
 
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n;
    string s;
    cin>>n;
    init(n);
    for(int i=1;i<=n;i++){
        cin>>s;
        unordered_set<char>tree;
        for(int j=0;j<s.size();j++){
            tree.insert(s[j]);
        }
        for(auto j=tree.begin();j!=tree.end();j++){
            vec[(*j)-'a'].push_back(i);
        }
    }
    for(int i=0;i<26;i++){
        for(int j=1;j<vec[i].size();j++){
            merge(vec[i][j-1],vec[i][j]);
        }
    }
    unordered_set<int>ans;
    for(int i=1;i<=n;i++){
        ans.insert(getfather(father[i]));
    }
    cout<<ans.size()<<endl;
    return 0;
}
View Code

E. Editor

题意:你要对文本进行编辑,你一开始的下标为起始点(文本范围是左边从起始点开始到右边可以为无穷远),你有n个操作,‘R’和‘L’分别是向右移动1格光标和向左移动一格光标(向左不能越过起始点),其他字符X为替换该光标对应位置的文本为X,每次操作后进行一个查询,查询全部文本的括号是否合法,若不合法输出-1,若合法则输出全部括号的最大深度。

思路:强制在线操作。对于所有的操作可以分为3类,添加括号,删除括号和无影响。(将起始点坐标视为1)在 i 位置添加一个 “(” ,则视为对区间 [ 1 , i ]所有数减一。i 位置添加一个“)”,则视为对区间[ 1 , i ]所有数加一。删除括号则相反。每次查询若左端点若为0且全部区间[1,n]的最小值大于0,则括号合法,且全部区间[1,n]的最大值为括号的最大深度。可以维护一颗线段树进行区间更新和维护区间最值。

#include <iostream>
#include <cstdio>
#define ll long long
using namespace std;
const ll MAXN = 1e6+10;
struct Tree {
        ll l,r;//节点左右端点
        ll sum;//求和
        ll lazy;//延迟标记
        ll maxn;//最大值
        ll minn;// 最小值
} tree[MAXN<<2];
char zifu[1000005];
void push_up(ll node) { 
    tree[node].sum=tree[node<<1].sum+tree[node<<1|1].sum;
    tree[node].maxn=max(tree[node<<1].maxn,tree[node<<1|1].maxn);
    tree[node].minn=min(tree[node<<1].minn,tree[node<<1|1].minn);
}
void push_down(ll node, ll length) {
    if(tree[node].lazy) { 
        tree[node<<1].lazy+=tree[node].lazy;
        tree[node<<1|1].lazy+=tree[node].lazy;
        tree[node<<1].sum+=(length-(length>>1))*tree[node].lazy;
        tree[node<<1|1].sum+=(length>>1)*tree[node].lazy;
        tree[node<<1].minn+=tree[node].lazy;
        tree[node<<1|1].minn+=tree[node].lazy;
        tree[node<<1].maxn+=tree[node].lazy;
        tree[node<<1|1].maxn+=tree[node].lazy;
        tree[node].lazy = 0;
    }
}
void build(ll l,ll r, ll node) { 
    tree[node].lazy = 0;
    tree[node].l=l;
    tree[node].r=r;
    if(l==r) {
        //cin>>tree[node].sum;
        tree[node].sum=0;
        tree[node].minn=tree[node].sum;
        tree[node].maxn=tree[node].sum;
        return;
    }
    ll mid=(l+r)>>1;
    build(l,mid,node<<1);
    build(mid+1,r,node<<1|1);
    push_up(node);
}
void update(ll left,ll right,ll key, ll node) { 
    if(tree[node].l>=left && tree[node].r<=right) {
        tree[node].sum+=(tree[node].r-tree[node].l+1)*key;
        tree[node].minn+=key;
        tree[node].maxn+=key;
        tree[node].lazy+=key;
        return;
    }
    push_down(node,tree[node].r-tree[node].l+1);
    ll mid=(tree[node].r+tree[node].l)>>1;
    if(left<=mid) update(left,right,key,node<<1);
    if(right>mid) update(left,right,key,node<<1|1);
    push_up(node);
}
ll query(ll left,ll right,ll node) { 
    if(tree[node].l>=left && tree[node].r<=right) {
        return tree[node].sum;
    }
    push_down(node,tree[node].r-tree[node].l+1);
    ll mid=(tree[node].r+tree[node].l)>>1;
    ll ans=0;
    if(left<=mid) ans+=query(left,right,node<<1);
    if(right>mid) ans+=query(left,right,node<<1|1);
    return ans;
}
ll query_min(ll left,ll right,ll node) { 
    if(tree[node].l>=left && tree[node].r<=right) {
        return tree[node].minn;
    }
    push_down(node,tree[node].r-tree[node].l+1);
    ll mid=(tree[node].r+tree[node].l)>>1;
    ll ans=0x7fffffff;
    if(left<=mid) ans=min(ans,query_min(left,right,node<<1));
    if(right>mid) ans=min(ans,query_min(left,right,node<<1|1)) ;
    return ans;
}
ll query_max(ll left,ll right,ll node) { 
    if(tree[node].l>=left && tree[node].r<=right) {
        return tree[node].maxn;
    }
    push_down(node,tree[node].r-tree[node].l+1);
    ll mid=(tree[node].r+tree[node].l)>>1;
    ll ans=-0x7fffffff;
    if(left<=mid) ans=max(ans,query_max(left,right,node<<1));
    if(right>mid) ans=max(ans,query_max(left,right,node<<1|1));
    return ans;
}
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int n,point=1,last_ans=0;
    cin>>n;
    build(1,n,1);
    string s;
    cin>>s;
    for(int i=0;i<s.size();i++){
        if(s[i]=='R'){
            cout<<last_ans<<" ";
            point++;
        }else if(s[i]=='L'){
            cout<<last_ans<<" ";
            point=max(1,point-1);
        }else{
            if(zifu[point]=='('){
                update(1,point,1,1);
            }else if(zifu[point]==')'){
                update(1,point,-1,1);
            }
            if(s[i]=='('){
                update(1,point,-1,1);
            }else if(s[i]==')'){
                update(1,point,1,1);
            }
 
            int minn=query_min(1,n,1);
            int maxx=query_max(1,n,1);
            int left_point=query(1,1,1);
            if(minn<0 || left_point!=0){
                cout<<-1<<" ";
                last_ans=-1;
            }else{
                cout<<maxx<<" ";
                last_ans=maxx;
            }
            zifu[point]=s[i];
        }
    }
    cout<<endl;
    return 0;
}
View Code
posted @ 2019-11-30 04:39  blacktion  阅读(262)  评论(0编辑  收藏  举报