竞赛链接:http://codeforces.com/contest/1101
A:找到一个被d整除,但是不被[l,r]包含的最小的数
解法:按照d和l的大小关系,分类讨论一下

#include <bits/stdc++.h>
using namespace std;
int d, l, r, q;
int main(){
    scanf("%d", &q);
    while(q--){
        scanf("%d%d%d", &l,&r,&d);
        int ans;
        if(d == 1){
            if(l > 1) printf("1\n");
            else printf("%d\n", r+1);
            continue;
        }
        if(d < l){
            ans = d;
        }else{
            ans = (r / d + 1) * d;
        }
        printf("%d\n", ans);
    }
}

B:题意,让我找一个最长的目标串长得像[:|||:] 这个样子,求中|是可以多个或者0个的
解法:直接扫描整个串找最左和最右的是[和]的位置,记作l,r,然后在l,r,里面找:最左和最右并且位置不同的位置记作x,y,最后统计一下x,y中间s[i]=’|'的个数,就得到目标串了,输出长度,在这种如果存在找不到,就输出非法信息即可。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 500010;
char s[maxn];

int main(){
    scanf("%s", s);
    int len = strlen(s);
    int pos1 = -1, pos2 = -1;
    for(int i = 0; i < len; i++){
        if(s[i] == '['){
            pos1 = i;
            break;
        }
    }
    for(int i = len-1; i >= 0; i--){
        if(s[i] == ']'){
            pos2 = i;
            break;
        }
    }
    if(pos1 == -1 || pos2 == -1 || pos1 > pos2){
        puts("-1");
        exit(0);
    }
    int pos3 = -1, pos4 = -1;
    for(int i = pos1; i <= pos2; i++){
        if(s[i] == ':'){
            pos3 = i;
            break;
        }
    }
    for(int i = pos2; i >= pos1; i--){
        if(s[i] == ':'){
            pos4 = i;
            break;
        }
    }
    if(pos3 >= pos4){
        puts("-1");
        exit(0);
    }
    int ans = 4;
    for(int i = pos3; i <= pos4; i++){
        if(s[i] == '|'){
            ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}

C:题意:给一堆线段,问是否可以把所有线段放到2个集合,使得这2个集合中任意选一个线段出来,即是第一个集合选一个,第2个集合选一下。
解法:很自然的想到按照l排序,l相同的时候按照r从小到大排序,然后依次扫描线段的过程中记录扫描过的线段的右端点的最大值,看一下是否当前线段的左端点大于右端点的最大值,如果大于,就从这里分界拆出集合就可以了。

#include <bits/stdc++.h>
using namespace std;
int T, n;
const int maxn = 1e5+10;
struct node{
    int l, r, id;
    bool operator<(const node &rhs)const{
        if(l == rhs.l) return r < rhs.r;
        return l < rhs.l;
    }
}a[maxn];
int out[maxn];
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d", &n);
        for(int i = 1; i <= n; i++){
            scanf("%d%d", &a[i].l, &a[i].r);
            a[i].id = i;
        }
        sort(a+1, a+n+1);
        int ans = -1;
        int mx = a[1].r;
        for(int i = 2; i <= n; i++){
            if(a[i].l > mx){
                ans = i;
                break;
            }else{
                mx = max(mx, a[i].r);
            }
        }
        if(ans == -1){
            printf("-1\n");
            continue;
        }
        for(int i = 1; i <= n; i++){
            if(i < ans){
                out[a[i].id] = 1;
            }else{
                out[a[i].id] = 2;
            }
        }
        for(int i = 1; i <= n; i++) printf("%d ", out[i]);
        printf("\n");
    }
    return 0;
}

D:https://blog.csdn.net/qq_38891827/article/details/86354057,树上dp,可以参考这个同学的题解。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+5;
//dp[i][j]表示为以i为起点的向i的子树延伸的gcd为a[i]的第j个质因子的最长链的长度
int a[maxn], dp[maxn][10];
//map[pair<i,j>]=k表示i在j中是第k个质因子
vector <int> G[maxn], vec[maxn];
map <pair<int, int>, int> mp;
int ans = 0;
void dfs(int rt, int fa){
    for(int i = 0; i < G[rt].size(); i++){
        dp[rt][i] = 1;
    }
    int mx1[10], mx2[10];
    for(int i = 0; i < 10; i++) mx1[i] = mx2[i] = 0;
    for(int i = 0; i < vec[rt].size(); i++){
        int to = vec[rt][i];
        if(to == fa) continue;
        dfs(to, rt);
        for(int j = 0; j < G[rt].size(); j++){
            if(a[to] % G[rt][j] == 0){
                int pos = mp[make_pair(G[rt][j], to)]; //rt的第j个质因子是to的第pos个质因子
                int tmp = dp[to][pos];
                if(mx1[j] < tmp){
                    mx2[j] = mx1[j];
                    mx1[j] = tmp;
                }else if(mx2[j] < tmp){
                    mx2[j] = tmp;
                }
            }
        }
    }
    for(int i = 0; i < G[rt].size(); i++){
        dp[rt][i] += mx1[i];
        ans = max(ans, mx1[i] + mx2[i] + 1);
    }
}
int main(){
    int n, u, v;
    scanf("%d", &n);
    for(int i=1; i<=n; i++) scanf("%d", &a[i]);
    for(int i=1; i<=n; i++){
        int tmp = a[i];
        for(int j=2; j*j<=tmp; j++){
            if(tmp%j == 0){
                G[i].push_back(j);
                mp[make_pair(j, i)] = G[i].size()-1;
                while(tmp%j == 0) tmp /= j;
            }
        }
        if(tmp > 1){
            G[i].push_back(tmp);
            mp[make_pair(tmp, i)] = G[i].size() - 1;
        }
    }
    for(int i = 1; i <= n-1; i++){
        scanf("%d%d", &u, &v);
        vec[u].push_back(v);
        vec[v].push_back(u);
    }
    dfs(1, -1);
    printf("%d\n", ans);
    return 0;
}

E:题意,这个题比d的难度小很多,就是一个人可能可以产生xy的小矩形(无数个),然后也可能查询已经有的小矩形是否可以填满当前xy这个大矩形?
解法:由于每种类型可以产生无数个,我们只用关心拥有的小矩形的长宽坐标是否在当前输入的范围内,是就可以完全填满。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5+5;

int main(){
    int q;
    scanf("%d", &q);
    int mx1 = 0, mx2 = 0;
    while(q--){
        char op[2];
        int x, y, minn, maxx;
        scanf("%s%d%d", op, &x, &y);
        minn = min(x, y);
        maxx = max(x, y);
        if(op[0] == '+'){
            mx1 = max(mx1, maxx);
            mx2 = max(mx2, minn);
        }else{
            if((x >= mx1 && y >= mx2) || (x >= mx2 && y >= mx1)) puts("YES");
            else puts("NO");
        }
    }
    return 0;
}

G:题意:将一个序列分成尽量多的段,每段值为异或值,且使得不存在非空子集异或和为0。
解法:转为前缀和,然后就是选最多元素且不存在非空子集异或和为0。然后插入线性基,线性基的大小即是答案。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 200010;
int n, a[maxn], b[maxn];
int p[33];

int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
        b[i] = b[i-1]^a[i];
    }
    if(b[n] == 0){
        puts("-1");
        return 0;
    }
    int ans = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 29; j >= 0; j--){
            if(!(b[i]>>j)) continue;
            if(!p[j]) {
                p[j] = b[i];
                ans++;
                break;
            }
            b[i] ^= p[j];
        }
    }
    printf("%d\n", ans);
    return 0;
}