2019/11/1 CSP simulation

Reflection EDITORIAL

The points still have to take part to get finished ah, + because I was lazy and slow and did not write the case of Figure daisy-chain the last question, in fact, these two points is not difficult. .
Although only \ (10pts \) , but enough to climb a length ah, additional \ (10pts \) in today's Volkswagen division \ (210pts \) look good is important in the context of
another \ (T2 \) I discovered last place to judge fake, but fortunately it seems to run within the data range move no problems, but still a good card to card, but this card is not only good luck next time to write or pay attention to the official not necessarily a card game

T1

\ (SB \) title
to \ (. 1 B == \) , determines the total number of all \ (GCD \) can not divisible \ (A \)
to \ (B == 2 \) , a total number of the smallest opening determines Fang is not strictly greater than \ (a \)
\ (sqrt () \) return value is a floating-point number to save my life, I almost want to take it, found to burst \ (long \ long \)

T2

Thinking

Bucket sets of barrels

Recording the number of samples of each letter string appears (the first layer), provided the number of occurrence of each letter \ (cnt_i \) , then the second layer \ (cnt_i \) representing a subscript, count the number of each letter appears number, denoted by \ (cnt1_i \)

for example

Original sample string

\(aabbbcccd\)

A first layer of the tub, the corresponding subscript letter: \ (2 \ 3 \ 3 \ 1 \)

The second layer bucket, the bucket index is assigned a value in the first layer: \ (1 \ 1 \ 3 \)

Consider a record \ (TOT \) sum, when we currently substring to enumerate and sample string of the second layer of the tub and the sum of absolute difference \ (0 \) , the second layer both each value in the correspondence of the bucket, i.e., can be obtained by transforming

Because every move is similar to the interval sliding window, so we just need to deal with the beginning of the interval, the interval after subtracting the left endpoint moved out, new entrants join the right endpoint to continue statistics answer

Code:

#include<bits/stdc++.h>
#define N (2000 + 10)
using namespace std;
inline int read() {
    int cnt = 0, f = 1; char c = getchar();
    while (!isdigit(c)) {if (c == '-') f = -f; c = getchar();}
    while (isdigit(c)) {cnt = (cnt << 3) + (cnt << 1) + (c ^ 48); c = getchar();}
    return cnt * f;
}
int T, n, Q, cnt[30], cnt1[30], g[N], f[N], q[N][30], l, r, ans, tmp, len, tot;
bool vis[N];
char ch; int s[N];
void add(int x, int sig) {
    /*
        因为挪动不关标本串的事,所以一切处理都在cnt1和f数组上,g只拿来比较 
    */ 
    if (f[cnt1[x]] > g[cnt1[x]]) --tot; else ++tot;  //因为要减去字母x原来出现次数的影响,所以同样影响到tot,把tot被影响的部分减掉 
    --f[cnt1[x]]; //外层桶减去字母x原来出现次数的影响 
    cnt1[x] += sig; //+1或-1,看是删除还是添加,更新内层桶 
    if (f[cnt1[x]] >= g[cnt1[x]]) ++tot; else --tot; //更新外层桶,和上面减的地方类似 
    ++f[cnt1[x]]; //外层桶加上字母x新出现次数的影响 
}
int main() {
    T = read();
    while (T--) {
        n = read(), Q = read();
        tmp = 0;
        for (; !isalpha(ch); ch = getchar());
        for (; isalpha(ch); ch = getchar()) s[++tmp] = ch - 'a' + 1;
        for (register int i = 1; i <= n; ++i) {  //整个串,每个字母出现次数的前缀和统计  
            for (register int j = 1; j <= 26; ++j) q[i][j] = q[i - 1][j]; //把前一个的答案继承过来,每个字母都要继承  
            ++q[i][s[i]]; //把这个字母的答案统计进去 
        } while (Q--) {
            /*
                cnt: 标本串的内层桶 cnt2:枚举区间的内层桶
                g:标本串的外层桶 f:枚举区间的外层桶 
            */
            for (register int i = 1; i <= 26; ++i) cnt[i] = cnt1[i] = 0;  //内层桶初始化 
            l = read(), r = read();
            len = r - l + 1;
            //当前在处理区间[1, len]这个子串(当前枚举的区间),即对于每个询问枚举的第一个区间 
            for (register int i = 1; i <= 26; ++i) {
                cnt[i] = q[r][i] - q[l - 1][i]; //处理标本串的每个字母的出现次数,前缀和减一下 
                cnt1[i] = q[len][i];  //处理当前子串的每个字母的出现次数 
                ++g[cnt[i]];  //对标本串字母出现次数的出现次数(外层桶)进行统计 
                ++f[cnt1[i]]; //对当前子串...............进行统计(中间同上) 
            }
            tot = 0;  //总和,初始化为0 
            for (register int i = 1; i <= 26; ++i) 
                if (!vis[cnt[i]]) vis[cnt[i]] = true, tot += g[cnt[i]];  
                /*
                    这里先把所有标本串的外层桶的值累加到tot上是为了防止包含的情况,如下例子
                    g(标本串): 1 1 2 3
                    f(当前区间) : 1 1 2
                    这实际上是一个不合法情况,不能统计进答案,但如果我们直接枚举在子串中出现的每个字母的出现次数就会出现这样的问题,所以先在前面加好
                    其实和处理完之后把剩下没有被枚举到的在标本串的内层桶中出现的元素累加上tot是一个效果,但这样需要多维护一个vis数组 
                */ 
            for (register int i = 1; i <= 26; ++i) vis[cnt[i]] = false;
            for (register int i = 1; i <= 26; ++i) 
                if (!vis[cnt1[i]]) {
                    vis[cnt1[i]] = true;
                    tot -= g[cnt1[i]];   //如果遇到在标本串和子串中同时出现的元素,先把这个减掉,防止影响后面统计答案 
                    if (f[cnt1[i]] > g[cnt1[i]]) tot += (f[cnt1[i]] - g[cnt1[i]]);
                    else tot += (g[cnt1[i]] - f[cnt1[i]]);
                    //上面两行就是取绝对值 
                }
            for (register int i = 1; i <= 26; ++i) vis[cnt1[i]] = false;
            ans = 0;
            if (!tot) ++ans;  //如果总和是0,增量答案 
            //处理完第一个区间,开始向后挪动,下面i枚举的是右端点 
            for (register int i = len + 1; i <= n; ++i) {
                add(s[i], 1);  //加入新右端点 
                add(s[i - len], -1);  //删除原左端点 
                if (!tot) ++ans;  //统计答案 
            } printf("%d\n", ans);
            for (register int i = 1; i <= 26; ++i) --g[cnt[i]], --f[cnt1[i]];  //初始化,相当于前面统计g和f的过程反过来 
        }
    }
    return 0;
}

T3

To be completed files, bloggers are writing

Guess you like

Origin www.cnblogs.com/kma093/p/11779732.html