1. 程式人生 > 其它 >The 15th Heilongjiang Provincial Collegiate Programming Contest

The 15th Heilongjiang Provincial Collegiate Programming Contest

https://codeforces.com/gym/102803

A: August

猜結論的題目,nt

B:Bills of Paradise

線段樹 四種操作:
1、查詢區間第一個比x大的數
2、刪除區間第一個比x大的數
3、區間所有小於x的數求和
4、將區間所有原來小於x的數還原

顯然權值線段樹維護區間最大值可以實現 1和2功能
可以通過維護區間和與區間最小值最大值實現 3功能
通過陣列記錄建樹時整棵樹的狀態可以實現 4功能 通過lz標記可以優化

const int maxn = 1e6 + 10;
unsigned long long k1, k2;

unsigned long long xorShift128Plus() {
    unsigned long long k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= k3 << 23;
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}

int n, m;
long long a[1000001], b[maxn], v[maxn];
char s[3];

struct seg{
    int t[maxn << 2], sum[maxn << 2], tv[maxn << 2], ts[maxn << 2], mx[maxn << 2], mn[maxn << 2];
    bool  lz[maxn << 2];
    #define root 1, 1, m
    #define node rt, l, r
    #define lr rt << 1
    #define rr rt << 1 | 1
    #define mid (l + r >> 1)
    #define lson lr, l, mid
    #define rson rr, mid + 1, r

    inline void push(int rt) {
        t[rt] = t[lr] + t[rr];
        sum[rt] = sum[lr] + sum[rr];
        mx[rt] = max(mx[lr], mx[rr]);
        mn[rt] = min(mn[lr], mn[rr]);
    }
    inline void upd(int rt, int l, int r) {
        lz[rt] = 1;
        t[rt] = tv[rt];
        sum[rt] = ts[rt];
        mx[rt] = b[r];
        mn[rt] = b[l];
    }
    inline void down(int rt, int l, int r) {
        lz[rt] = 0;
        upd(lson); upd(rson);
    }
    void build(int rt, int l, int r) {
        if(l == r) {
            tv[rt] = t[rt] = v[l];
            ts[rt] = sum[rt] = b[l] * v[l];
            mx[rt] = mn[rt] = b[l];
            return ;
        }
        build(lson); build(rson);
        tv[rt] = tv[lr] + tv[rr];
        ts[rt] = ts[lr] + ts[rr];
        push(rt);
    }

    int queryup(int rt, int l, int r, int x) {
        if(l == r) return b[l];
        if(lz[rt])  down(node);
        if(mx[lr] >= x) return queryup(lson, x);
        else if(mx[rr] >= x) return queryup(rson, x);
        return 1e12;
    }

    int querysum(int rt, int l, int r, int x) {
        if(mn[rt] > x) return 0;
        if(mx[rt] <= x)  return sum[rt];
        if(lz[rt])  down(node);
        return querysum(lson, x) + querysum(rson, x);
    }

    void reinit(int rt, int l, int r, int x) {
        //printf("%lld %lld %lld %lld %lld\n", rt, l, r, b[l], b[r]);
        if(b[l] > x)    return ;
        if(b[r] <= x)   {
            upd(node);
            return ;
        }
        if(lz[rt])  down(node);
        else {
            reinit(lson, x);
            reinit(rson, x);
        }
        push(rt);
    }

    void change(int rt, int l, int r, int x) {
        if(l == r) {
            t[rt] --;   sum[rt] -= b[l];
            if(t[rt] == 0)  mx[rt] = 0, mn[rt] = 0x3f3f3f3f3f3f3f3f;
            return ;
        }
        if(lz[rt])  down(node);
        if(mx[lr] >= x) change(lson, x);
        else if(mx[rr] >= x) change(rson, x);
        push(rt);
    }
}T;

void gen() {
    scanf("%d %llu %llu", &n, &k1, &k2);
    for (int i = 1; i <= n; i++) {
        a[i] = xorShift128Plus() % 999999999999 + 1;
    }
    sort(a + 1, a + 1 + n); m = 1; int sum = 0;
    for(int i = 1; i <= n; ++ i)    {
        v[m] ++;  sum += a[i];
        if(a[i] != a[i + 1])    b[m++] = a[i];
    } m--;
    T.build(root);
    //for(int i = 1; i <= m; ++ i)    printf("%lld%c", b[i], " \n"[i == m]);
    int q = rd();
    //printf("%lld %lld\n", T.querysum(root, 1e13), sum);
    for(int i = 1; i <= q; ++ i) {
        scanf("%s", s); int x = rd();
        if(s[0] == 'F') printf("%lld\n", T.queryup(root, x));
        else if(s[0] == 'D') T.change(root, x);
        else if(s[0] == 'C') printf("%lld\n", T.querysum(root, x));
        else T.reinit(root, x);
        //printf("%lld\n", T.querysum(root, 1e12));
    }
}

signed main() {
    gen();
    return 0;
}


C: Cornelia Street

超級無敵大水題,看起來什麼迴圈節好像要kmp,複雜度都算不出來,結果暴力列舉N^2隨便過

const int maxn = 1e6 + 10;
int n, m, len, pos;
char s[maxn];
bool ok(int l, int &pos) {
    int nowpos = -1; pos = -1;
    for(int i = l; i < len; ++ i) if(s[i % l] != s[i]) {
        pos = i - i % l;    break;
    }
    if(pos == -1 || pos + 2 * l > len)   return 0;
    for(int i = pos + l; i < len; ++ i) if(s[pos + i % l] != s[i]) {
        nowpos = i - i % l; if(nowpos + l > len)   return 0;
        for(int j = nowpos; j < len; ++ j)  if(s[j % l] != s[j]) return 0;
        break;
    }
    if(nowpos == -1)    return 0;
    return 1;
}

signed main() {
    scanf("%s", s); len = strlen(s);
    for(int i = 1, up = len / 3; i <= up; ++ i) {
        if(ok(i, pos)) {
            for(int j = 0; j < i; ++ j) printf("%c", s[j]); printf(" ");
            for(int j = 0; j < i; ++ j) printf("%c", s[j + pos]);   puts("");
            return 0;
        }
    }
    return 0;
}

F:False God

nt dp
讀題以為是互吃,我的回合碰到你就能吃你
實際上是隻要小兵碰到你就會被吃,不管是你主動還是被動,那直接按位置排序,n^2dp暴力轉移狀態

struct node{
    int x, y;
    bool operator < (const node &a) const {
        return y == a.y ? x < a.x : y > a.y;
    }
}a[maxn];
int dp[maxn];
signed main() {
    int t = rd();
    while(t--) {
        int sx = rd(), sy = rd();
        int n = rd();
        for(int i = 1; i <= n; ++ i)    a[i].x = rd(), a[i].y = rd();
        sort(a + 1, a + 1 + n); //puts("");
        for(int i = 1; i <= n; ++ i) {
            dp[i] = 1;  //  printf("%lld %lld\n", a[i].x, a[i].y);
            for(int j = 1; j < i; ++ j) {
                if(abs(a[i].x - a[j].x) - 1 <= a[j].y - a[i].y)    dp[i] = max(dp[i], dp[j] + 1);
            }
        }
        int ans = 0;
        //for(int i = 1; i <= n; ++ i)    printf("%lld%c", dp[i], " \n"[i == n]);
        for(int i = 1; i <= n; ++ i)    if(sy <= a[i].y + 1 && abs(sx - a[i].x) - 1 <= a[i].y - sy)    ans = max(ans, dp[i]);
        printf("%lld\n", ans);
    }
    return 0;
}

G: Goodbye

簡單思維題

H:Hate That You Know Me

\(k\in(0,1,2,3)\),求

\[\sum_{i = 1}^n \sum_{d|i}d^k \]

顯然轉化為整除分塊,\(d^k\) 通過公式O(1)求
\(mod = 1<<64\)顯然是unsigned long long 的自然溢位

const int mod = (1 << 64);
//n * n * (n + 1) * (n + 1) / 4
 
inline int sum(int sta, int n) {
    if(sta == 3)    {
        if(n & 1)   return (n + 1) / 2 * ((n + 1) / 2) * n * n;
        else return n / 2 * (n / 2) * (n + 1) * (n + 1);
    }
    else if(sta == 2)   {
        if(n & 1) {
            if(n % 3 == 0)  return (n + 1) / 2 * (n / 3) * (2 * n + 1);
            else if((n + 1) % 3 == 0)   return (n + 1) / 6 * n * (2 * n + 1);
            else return (n + 1) / 2 * n * ((2 * n + 1) / 3);
        }
        else {
            if(n % 3 == 0)  return n / 6 * (n + 1) * (2 * n + 1);
            else if((n + 1) % 3 == 0)   return (n + 1) / 3 * (n / 2) * (2 * n + 1);
            else return (2 * n + 1) / 3 * (n / 2) * (n + 1);
        }
    }
    else if(sta)    {
        if(n & 1)   return (n + 1) / 2 * n;
        else    return  n / 2 * (n + 1);
    }
    else return n;
}/*
inline int sum(int sta, int n) {
    if(sta == 3)    return n * n * (n + 1) * (n + 1) / 4;
    else if(sta == 2)   return (2 * n + 1) * (n) * (n + 1) / 6;
    else if(sta) return n * (n + 1) / 2;
    else return n;
}*/
inline void qmod(int &a) {
    if(a >= mod)    a -= mod;
}
void solve3() {//n * (n + 1) * (2n + 1) / 6
    int a = rd(), b = rd(), n = rd();
    int ans1 = 0, ans2 = 0;
    for(int l = 1, r; l <= n; l = r + 1) {
        r = n / (n / l);
        ans1 += n / l * (sum(a, r) - sum(a, l - 1));
        ans2 += n / l * (sum(b, r) - sum(b, l - 1));
    }
    printf("%llu\n", ans1 ^ ans2);
}
 
signed main() {
    solve3();
    return 0;
}

K: Keeping A Secret

滾遠點謝謝

L:Let's Get Married

找規律構造