codeforces-1144 (div3)

赛后经验:div3过于简单,以后不做了

A.存在以下情况即为NO

1.存在相同字母 2.最大字母-最小字母 != 字符串长度

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
bool vis[maxn];
char str[maxn];
int main(){
    int T = read();
    while(T--){
        scanf("%s",str);
        int l = strlen(str);
        int MIN = INF,MAX = 0,flag = 1;
        for(int i = 0 ; i < 30; i ++) vis[i] = 0;
        for(int i = 0 ; i < l ; i ++){
            if(vis[str[i] - 'a']){
                flag = 0;
                continue;
            }
            vis[str[i] - 'a'] = 1;
            MIN = min(MIN,str[i] - 'a');
            MAX = max(MAX,str[i] - 'a');
        }
        if(MAX - MIN + 1 == l && flag){
            puts("Yes");
        }else{
            puts("No");
        }
    }    
    return 0;
}
A

B.设奇数字母cnt1个,偶数字母cnt2个

假设cnt1 >= cnt2 最多留下(cnt1 - cnt2 - 1)个奇数字母,偶数同理

取最小的保留就可以了

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 2010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int even[maxn],odd[maxn];
int main(){
    Sca(N);
    int cnt1 = 0,cnt2 = 0;
    for(int i = 1; i <= N ; i ++){
        int x = read();
        if(x & 1) odd[++cnt1] = x;
        else even[++cnt2] = x;
    }
    sort(odd + 1,odd + cnt1 + 1);
    sort(even + 1,even + 1 + cnt2);
    if(abs(cnt1 - cnt2) <= 1){
        puts("0");
    }else if(cnt1 > cnt2){
        LL sum = 0;
        for(int i = 1; i <= cnt1 - cnt2 - 1;i ++) sum += odd[i];
        Prl(sum);
    }else{
        LL sum = 0;
        for(int i = 1; i <= cnt2 - cnt1 - 1;i ++) sum += even[i];
        Prl(sum);
    }
    return 0;
}
B

C.很显然一个数出现次数超过3次就NO

第一个数列输出所有次数 >= 1的数

第二个数列输出所有次数 >= 2的数即可

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int a[maxn];
int ans[maxn];
int main(){
    Sca(N);
    int MAX = -1,MIN = INF;
    bool flag = 1;
    for(int i = 1; i <= N; i ++){
        int x = read();
        a[x]++;
        if(a[x] > 2) flag = 0;
        MAX = max(MAX,x); MIN = min(MIN,x);
    }
    if(!flag){
        puts("NO");
        return 0;
    }
    puts("YES");
    int top = 0;
    for(int i = MIN; i <= MAX; i ++){
        if(a[i]){
            a[i]--;
            ans[++top] = i;
        }
    }
    Pri(top);
    for(int i = 1; i <= top; i ++) printf("%d ",ans[i]);
    puts("");
    top = 0;
    for(int i = MAX; i >= MIN; i --){
        if(a[i]) ans[++top] = i;
    }
    Pri(top);
    for(int i = 1; i <= top; i ++) printf("%d ",ans[i]);
    puts("");
    return 0;
}
C

D.仔细一看就会发现操作就是把一个数变为相邻的一个数。

那么出现最多次数的数不变,其余的都变成他就可以了。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int a[maxn];
int num[maxn];
int main(){
    Sca(N);
    int MAX = 0;
    for(int i = 1; i <= N ; i ++){
        Sca(a[i]); num[a[i]]++;
        if(num[MAX] < num[a[i]]) MAX = a[i];
    } 
    int root = 1;
    int ans = 0;
    Pri(N - num[MAX]);
    for(int i = 1; i <= N ; i ++){
        if(a[i] == MAX){
            root = i;
            break;
        }
    }
    for(int i = root + 1; i <= N; i ++){
        if(a[i] > a[i - 1]) printf("2 %d %d
",i,i - 1);
        else if(a[i] < a[i - 1]) printf("1 %d %d
",i,i - 1);
        a[i] = a[i - 1];
    }
    for(int i = root - 1; i >= 1; i --){
        if(a[i] > a[i + 1]) printf("2 %d %d
",i,i + 1);
        else if(a[i] < a[i + 1]) printf("1 %d %d
",i,i + 1);
        a[i] = a[i + 1];
    }
    return 0;
}
D

E.模拟26进制加减法即可。具体操作就是(a + b) / 2

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
char a[maxn],b[maxn];
int c[maxn];
int main(){
    N = read();
    scanf("%s%s",a + 1,b + 1);
    for(int i = N ; i >= 1; i--){
        c[i] += b[i] + a[i] - 'a' - 'a' + 2;
        while(c[i] > 27){
            c[i] -= 26;
            c[i - 1]++;
        }    
    }    
    int zero = 1;
    for(int i = 0 ; i <= N ; i ++){
        if(c[i] & 1){
            c[i]--;
            c[i + 1] += 26;
        }
        c[i] /= 2;
        if(c[i]) zero = 0;
        if(!zero) printf("%c",c[i] + 'a' - 1);
    }
    return 0;
}
E

F.意识到一个点不会即有入度又有出度,那么所有点就分为了出度点和入度点。

直接图上染色即可。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 2e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
struct Edge{
    int to,next;
}edge[maxn * 2];
int head[maxn],tot;
void init(){
    for(int i = 0 ; i <= N; i ++) head[i] = -1;
    tot = 0;
}
void add(int u,int v){
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
int color[maxn];
bool flag = 1;
void dfs(int t){
    if(!flag) return;
    for(int i = head[t]; ~i ; i = edge[i].next){
        int v = edge[i].to;
        if(color[v] == color[t]){
            flag = 0;
            return;
        }
        if(color[v] == 3 - color[t]) continue;
        color[v] = 3 - color[t];
        dfs(v);
    }
}
PII E[maxn];
int main(){
    Sca2(N,M); init();
    for(int i = 1; i <= M; i ++){
        int u = read(),v = read();
        add(u,v); add(v,u);
        E[i] = mp(u,v);
    }
    for(int i = 1; i <= N && flag; i ++){
        if(!color[i]){
            color[i] = 1;
            dfs(i);
        }
    }
    if(!flag){
        puts("NO"); return 0;
    }else{
        puts("YES");
    }
    for(int i = 1; i <= M ; i ++){
        if(color[E[i].fi] == 1) printf("1");
        else printf("0");
    }
    return 0;
}
F

G.题目的一个子问题是序列中的一个区间能否分为递增和递减

意识到一个区间最小的点,只能作为递增的起点或者递减的终点,在知道了这个条件下,另一边就已知必须递增或者递减。

预处理出每个点为起点的最大递增终点和最大递减终点。

用solve(l,r,lMIN,lMAX,rMIN,rMAX)表示在l到r这段区间内,递减段的数字被限制在lMIN到lMAX内,递增段的数字被限制在rMIN,rMAX内,在此基础上求是否可行。

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)  
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))  
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);  
#define Pri(x) printf("%d
", x)
#define Prl(x) printf("%lld
",x);  
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long  
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second 
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double eps = 1e-9;
const int maxn = 8e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int a[maxn],Hash[maxn];
struct tree{
    int l,r,MIN;
}tree[maxn << 2];
void Pushup(int t){
    if(a[tree[t << 1].MIN] < a[tree[t << 1 | 1].MIN]) tree[t].MIN = tree[t << 1].MIN;
    else tree[t].MIN = tree[t << 1 | 1].MIN;
}
void Build(int t,int l,int r){
    tree[t].l = l; tree[t].r = r;
    if(l == r){
        tree[t].MIN = l;
        return;
    }
    int m = l + r >> 1;
    Build(t << 1,l,m); Build(t << 1 | 1,m + 1,r);
    Pushup(t);
}
int query(int t,int l,int r){
    if(l <= tree[t].l && tree[t].r <= r) return tree[t].MIN;
    int m = tree[t].l + tree[t].r >> 1;
    if(r <= m) return query(t << 1,l,r);
    else if(l > m) return query(t << 1 | 1,l,r);
    else{
        int p1 = query(t << 1,l,m),p2 = query(t << 1 | 1,m + 1,r);
        if(a[p1] > a[p2]) return p2;
        return p1;
    }
}
int ans[maxn];
int radd[maxn],rdel[maxn];
bool solve(int L,int R,int lMIN,int lMAX,int rMIN,int rMAX){
    if(L > R) return true;
    if(L == R){
        if(rMIN < a[L] && a[L] < rMAX){
            ans[L] = 0;
            return true;
        }
        if(lMIN < a[L] && a[L] < lMAX){
            ans[L] = 1;
            return true;
        }
        return false;
    }
    int p = query(1,L,R);
    if(lMIN < a[p] && a[p] < lMAX && (p == R || (radd[p + 1] >= R && a[p + 1] > rMIN && a[p + 1] < rMAX && a[R] < rMAX && a[R] > rMIN))){
        if(solve(L,p - 1,a[p],lMAX,rMIN,p == R?rMAX:a[p + 1])){
            ans[p] = 1;
            for(int j = p + 1; j <= R; j ++) ans[j] = 0;
            return true;
        }
    }
    if(rMIN < a[p] && a[p] < rMAX && (p == L || (rdel[L] >= p - 1 && a[L] > lMIN && a[L] < lMAX && a[p - 1] < lMAX && a[p - 1] > lMIN))){
        if(solve(p + 1,R,lMIN,p == L?lMAX:a[p - 1],a[p],rMAX)){
            ans[p] = 0;
            for(int j = L; j <= p - 1; j ++) ans[j] = 1;
            return true;
        }
    }
    return false;
} 
int main(){
    Sca(N);
    for(int i = 1; i <= N ; i ++) a[i] = read();
    radd[N] = rdel[N] = N;
    for(int i = N - 1; i >= 1; i --){
        if(a[i] < a[i + 1]) radd[i] = radd[i + 1];
        else radd[i] = i;
        if(a[i] > a[i + 1]) rdel[i] = rdel[i + 1];
        else rdel[i] = i;
    }
    Build(1,1,N);
    if(solve(1,N,-INF,INF,-INF,INF)){
        puts("YES");
        for(int i = 1; i <= N ; i ++) printf("%d ",ans[i]);
    }else{
        puts("NO");
    }
    return 0;
}
G
 
原文地址:https://www.cnblogs.com/Hugh-Locke/p/10763846.html