codeforces-1131 (div2)

A.把右上角的凹缺口补上变成凸的就成了规则矩形

#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 = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int main(){
    LL w1,h1,w2,h2;
    scanf("%lld%lld%lld%lld",&w1,&h1,&w2,&h2);
    LL ans = w1 + w1 + h1 + h1 + h2 + h2 + 4;
    Prl(ans);
    return 0;
}
A

B.画在图上就是两条斜线之间有多少可以水平的线,显然是下面这条线的最高点和上面这条线的最低点作差,记得打一个vis标记记录哪些线取过了

#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 = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int main(){
    Sca(N);
    LL la = 0,lb = 0;
    LL ans = 1;
    LL now = 1;
    for(int i = 1; i <= N ; i ++){
        LL a,b; scanf("%lld%lld",&a,&b);
        int t = max(max(la,lb),now);
        if(min(a,b) >= t){
            ans += min(a,b) - t + 1;
            now = min(a,b) + 1;
        }
        la = a; lb = b;
    }
    Prl(ans);
    return 0;
}
B

C.开始觉得要二分,后来觉得要O(n3),仔细一看发现O(n)

显然取两条非递减的线,从最高点往两边降低,贪心的发现每次都升高最高点更低的那个路径就可以了。

#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 = 110;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int a[maxn];
int b[maxn],c[maxn];
int main(){
    Sca(N);
    for(int i = 1; i <= N ; i ++) Sca(a[i]);
    sort(a + 1,a + 1 + N);
    int cnt1 = 0,cnt2 = 0;
    b[++cnt1] = a[1];
    c[++cnt2] = a[2];
    for(int i = 3; i <= N ; i ++){
        if(b[cnt1] < c[cnt2]) b[++cnt1] = a[i];
        else c[++cnt2] = a[i];
    }
    for(int i = 1; i <= cnt1; i ++) printf("%d ",b[i]);
    for(int i = cnt2; i >= 1; i --) printf("%d ",c[i]);
    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 = 2010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
char MAP[maxn][maxn];
struct Edge{
    int to,next;
}edge[maxn * maxn * 2];
int fa[maxn * 2],tot,head[maxn * 2],ind[maxn * 2];
void init(){
    for(int i = 0 ; i <= N + M; i ++){
        head[i] = -1;
        fa[i] = i;
        ind[i] = 0;
    } 
    tot = 0;
}
void add(int u,int v){
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
int find(int x){
    if(x == fa[x]) return x;
    return fa[x] = find(fa[x]);
}
void Union(int a,int b){
    a = find(a); b = find(b);
    fa[a] = b;
}
int ans[maxn];
int main(){
    Sca2(N,M); init();
    bool flag = 1;
    for(int i = 1; i <= N ; i ++){
        scanf("%s",MAP[i] + 1);
        for(int j = 1; j <= M ; j ++){
            if(MAP[i][j] == '='){
                Union(i,j + N);
            }
        }
    }
    for(int i = 1; i <= N && flag; i ++){
        for(int j = 1; j <= M ; j ++){
            if(MAP[i][j] == '=') continue;
            int a = find(i),b = find(j + N);
            if(a == b){
                flag = 0;
                break;
            }
            if(MAP[i][j] == '>'){
                add(b,a); ind[a]++;
            }else{
                add(a,b); ind[b]++;
            }
        }
    }
    if(!flag){
        puts("No");
        return 0;
    }
    queue<int>Q;
    for(int i = 1; i <= N + M; i ++){
        if(find(i) == i && !ind[i]){
            ans[i] = 1;
            Q.push(i);
        } 
    }
    while(!Q.empty()){
        int u = Q.front(); Q.pop();
        for(int i = head[u]; ~i; i = edge[i].next){
            int v = edge[i].to;
            ans[v] = max(ans[v],ans[u] + 1);
            ind[v]--;
            if(!ind[v]) Q.push(v);
        }
    }
    for(int i = 1; i <= N + M; i ++){
        if(fa[i] == i && ind[i]) flag = 0;
    }
    if(!flag){
        puts("No");
        return 0;
    }
    puts("Yes");
    for(int i = 1; i <= N ; i ++){
        printf("%d ",ans[find(i)]);
    }
    puts("");
    for(int j = N + 1; j <= N + M; j ++){
        printf("%d ",ans[find(j)]);
    }
    return 0;
}
D

E.dp[100000][30]记录到i这个字符串j的最长长度。

如果右边的字符串都为k,那么dp[i][j] = max(dp[i][j],len * (dp[i - 1][j] + 1) + dp[i - 1][j]);

否则字符就变为前后缀与他相同的最长长度相加

如果曾经出现过这个字符,这个字符的出现次数至少为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 = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
LL ans[40];
LL dp[maxn][30];
LL pre[100000];
LL tmp[30];
char str[100000];
int main(){
    Sca(N);
    for(int i = 1; i <= N ; i ++){
        scanf("%s",str);
        LL len = strlen(str);
        LL a = 1,b = len;
        for(int j = 0 ; j < 26; j ++) tmp[j] = 0;
        for(int j = 0; j < len; j ++){
            if(j && str[j - 1] == str[j]) pre[j] = pre[j - 1] + 1;
            else pre[j] = 1;
            tmp[str[j] - 'a'] = max(tmp[str[j] - 'a'],pre[j]);
        }
        for(int j = 0 ; j < 26; j ++){
            dp[i][j] = tmp[j];
            int l = 0,r = len - 1;
            while(l <= r && str[l] == j + 'a') l++;
            while(r > l && j + 'a' == str[r]) r--;
            if(l == len){
                dp[i][j] = max(dp[i][j],len * (dp[i - 1][j] + 1) + dp[i - 1][j]);    
            }else if(dp[i - 1][j]){
                dp[i][j] = max(dp[i][j],l + len - r);
            }
        } 
    }
    LL sum = 0;
    for(int j = 0 ; j < 26; j ++) sum = max(sum,dp[N][j]);
    Prl(sum);
    return 0;
}
E

F.喜闻乐见的送分F题,开到就是赚到。

并查集模板题,加一个l[maxn],r[maxn]表示这个集合最左最右的数字

nxt[maxn]表示这个数字的下一个数字,每次匹配u,v都把u集合放在v集合的左边,更新一下几个数组

#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 = 150010;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7; 
int N,M,K;
int fa[maxn],r[maxn],l[maxn];
int nxt[maxn];
void init(){
    for(int i = 0 ; i <= N ; i ++){
        fa[i] = r[i] = l[i] = i;
        nxt[i] = -1;
    } 
}
int find(int x){
    if(x == fa[x]) return x;
    return fa[x] = find(fa[x]);
}
int main(){
    Sca(N);    init();
    for(int i = 1; i <= N - 1; i ++){
        int u,v; Sca2(u,v);
        u = find(u); v = find(v);
        nxt[r[u]] = l[v];
        l[v] = l[u];
        fa[u] = v;
    }
    int root = l[find(1)];
    for(int i = 1; i <= N ; i ++){
        printf("%d ",root);
        root = nxt[root];
    }
    return 0;
}
F
原文地址:https://www.cnblogs.com/Hugh-Locke/p/10725924.html