【补题】Codeforces Round #506 (Div. 3)

A. Many Equal Substrings

题解

找出最长的和后缀相等的前缀,反复输出除去前缀的剩下部分即可啦。

代码

#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = (int)1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n, k;
char str[nmax];
int main() {
    while (scanf("%d %d", &n, &k) != EOF) {
        scanf("%s", str + 1);
        int ans = 0;
        for(int len = n - 1; len >= 1; -- len) {
            bool isok = true;
            for(int i = 1; i <= len; ++i)
                if(str[i] != str[n - len + i]) {
                    isok = false;
                    break;
                }
            if(isok) {
                ans = len;
                break;
            }
        }
//        printf("debug %d\n", ans);
        printf("%s", str + 1);
        for(int i = 1; i < k; ++i) {
            for(int j = ans + 1; j <= n; ++j) {
                printf("%c", str[j]);
            }
        }
    }
    return 0;
}

B. Creating the Contest

题解

用队列存一下当前数字的目标(即数字的两倍)。每次判断一个数字是否小于等于当前队列的队头,若是的话,那么说明可以找到一个数字满足上一个数字的要求,那么上一个数字的目标(即他的两倍)出队,计数器加一。 若不满足要求的话,让上一个数字做为序列的尾部,因为他可以满足找不到数字满足要求。一边统计一边更新答案即可。
注意最后队列里还有元素,计数器还要加一,同时更新答案。否则会漏掉答案出现在序列末尾的情况。

代码

#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n;
int a[nmax];
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i)
        scanf("%d", &a[i]);
    queue<int> q;
    int cnt = 0, ans = 0;
    for(int i = 1; i <= n; ++i) {
        if(q.empty()) {
            q.push(2 * a[i]);
        } else {
            int now = q.front();
            if(a[i] <= now) {
                q.pop();
                cnt ++;
                q.push(2 * a[i]);
            } else {
                ans = max(ans, cnt + 1);
                while(!q.empty()) q.pop();
                q.push(2 * a[i]);
                cnt = 0;
            }
        }
    }
    if(!q.empty()) {
        ans = max(ans, cnt + 1);
    }
    printf("%d\n" ,ans);
    return 0;
}

C. Maximal Intersection

题解

对于 n n 个序列的相交部分,可以认为是 n n 个序列的左端点的最大值和右端点的最小值的差。如果左端点最大值还比右端点最小值大,说明没有相交的部分。
所以对于左右端点分别来看,ST预处理左端点的最大值和右端点的最小值,每次只需要看一下 max([l1,li1],[ii+1,in]) m a x ( [ l 1 , l i − 1 ] , [ i i + 1 , i n ] ) min([r1,ri1],[ri+1,rn]) m i n ( [ r 1 , r i − 1 ] , [ r i + 1 , r n ] ) 的相交情况,更新答案。

代码

#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int n;
int l[nmax], r[nmax];
int dpl[nmax][(int)(log2(1e6+7) + 10)], dpr[nmax][(int)(log2(1e6+7) + 10)];
void getRMQ() {
    for (int i = 1; i <= n; ++i)
        dpl[i][0] = l[i];
    for (int j = 1; (1 << j) <= n ; ++j)
        for (int i = 1; i + ( 1 << j ) - 1 <= n; ++i)
            dpl[i][j] = max(dpl[i][j - 1], dpl[i + (1 << (j - 1 ))][j - 1]);
    for (int i = 1; i <= n; ++i)
        dpr[i][0] = r[i];
    for (int j = 1; (1 << j) <= n ; ++j)
        for (int i = 1; i + ( 1 << j ) - 1 <= n; ++i)
            dpr[i][j] = min(dpr[i][j - 1], dpr[i + (1 << (j - 1 ))][j - 1]);
}
int RMQmax(int l, int r) {
    int k = 0;
    while ( (1 << (k + 1)) <= r - l + 1) ++k;
    return max(dpl[l][k], dpl[r - (1 << k) + 1][k]);
}
int RMQmin(int l, int r) {
    int k = 0;
    while ( (1 << (k + 1)) <= r - l + 1) ++k;
    return min(dpr[l][k], dpr[r - (1 << k) + 1][k]);
}
int getans(int l, int r) {
    if(r <= l) return 0;
    else return r - l;
}
int main() {
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) {
        scanf("%d %d", &l[i], & r[i]);
    }
    getRMQ();
    int ans = 0, tmp = 0;
    for(int i = 1; i <= n; ++i) {
        if(i == 1) {
            int ll = RMQmax(2, n);
            int rr = RMQmin(2, n);
            tmp = getans(ll, rr);
            ans = max(ans, tmp);
        } else if(i == n) {
            int ll = RMQmax(1, n - 1);
            int rr = RMQmin(1, n - 1);
            tmp = getans(ll, rr);
            ans = max(ans, tmp);
        } else {
            int ll = max(RMQmax(1, i-1), RMQmax(i + 1, n));
            int rr = min(RMQmin(1, i-1), RMQmin(i + 1, n));
            ans = max(ans, getans(ll, rr));
        }
    }
    printf("%d\n", ans);
    return 0;
}

D. Concatenated Multiples

题解

这题的hack数据卡常数,是真的坑爹。
做法很简单,看看数字中出现的数字的位数都有哪些。预处理出所有的数字 mod k m o d   k 的值存进对应数字位数的map中,然后搞一搞余数就好了

代码

#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 1e6+7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
map <int, int> mp[15];
bool isocc[20];
int a[nmax];
int zeors[20];
int n, k;
int digits[nmax];
int main(){
    scanf("%d %d", &n, &k);
    for(int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
        digits[i] = log10(a[i]) + 1;
        mp[digits[i]][a[i] % k] ++;
//        isocc[digits[i]] = true;
    }
    ll ans = 0;
    for(int i = 1; i <= n; ++i) {
        ll tmp = a[i] % k;
        mp[digits[i]][tmp] --;
        for(int j = 1; j <= 10; ++j) {
            tmp = (tmp * 10 ) % k;
            if(mp[j].count((k - tmp % k) % k) > 0)
                ans += mp[j][(k - tmp % k) % k];
//            if(isocc[j])
        }
        mp[digits[i]][a[i] % k] ++;
    }
    printf("%I64d\n", ans);
    return 0;
}

E. Tree with Small Distances

题解

树形dp或者贪心。

代码

#include
using namespace std;
typedef double db;
typedef long long ll;
typedef unsigned long long ull;
const int nmax = 2e5 + 7;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const ull p = 67;
const ull MOD = 1610612741;
int head[nmax], tot, ans;
bool iscover[nmax];
struct edge {
    int to, nxt;
}e[nmax<<1];
void add_edge(int u, int v) {
    e[tot].to = v;
    e[tot].nxt = head[u];
    head[u] = tot++;
}
int n;
void update(int u) {
    for(int i = head[u]; i != -1; i = e[i].nxt) {
        iscover[e[i].to] = true;
    }
    iscover[u] = true;
}
void dfs(int u, int f) {
    for(int i = head[u]; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if(v != f) {
            dfs(v, u);
        }
    }
    for(int i = head[u]; i != -1; i = e[i].nxt) {
        int v = e[i].to;
        if(v != f && !iscover[v]) {
            update(u);
            ans ++;
        }

    }
}
int main() {
    while (scanf("%d", &n) != EOF) {
        memset(head, -1, sizeof(head));
//        memset(iscover, 0 , sizeof iscover);
        tot = ans = 0;
        for(int i = 1; i <= n - 1; ++i) {
            int u ,v;
            scanf("%d %d", &u, &v);
            add_edge(u, v);
            add_edge(v, u);
        }
        update(1);
//        iscover[1] = true;
        for(int i = head[1]; i != -1; i = e[i].nxt) {
            update(e[i].to);
        }
        dfs(1, -1);
        printf("%d\n", ans);
    }
    return 0;
}

你可能感兴趣的:(【补题】Codeforces Round #506 (Div. 3))