【AtCoder】Tenka1 Programmer Contest(C - F)

C - Align

考的時候,我大膽猜告終論,就是一小一大一小一大這麼排
證實的話,因爲咱們老是要加上相鄰的最大值而減去最小值,咱們就讓最大值都保持在前面ios

若是長度爲奇數,要麼就是大小大小大,要麼是小大小大小
第一種要求是靠中間的位置填(n + 1) / 2個最大值中較大的,兩邊填較小的(兩邊只被加了一次)
第二種要求是靠中間的位置填(n + 1) / 2個最小值中較小的,兩邊填較大的(兩邊被減了一次)c++

若是長度爲偶數
小大小大小大和大小大小大小顯然等價ui

咱們把最小值中較大的放在最前,最大值較小的放在最後便可spa

代碼

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
//#define ivorysi
#define MAXN 100005
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
int N;
int A[MAXN];
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(N);
    for(int i = 1 ; i <= N ; ++i) read(A[i]);
    sort(A + 1,A + N + 1);
    if(N & 1) {
        int t = N / 2 + 1;
        int L = 1,R = N;int64 res = 0;
        for(int i = 1 ; i <= t - 2; ++i) {
            res -= 2 * A[i];
        }
        res = res - A[t - 1] - A[t];
        for(int i = t + 1 ; i <= N ; ++i) res += 2 * A[i];
        int64 tmp = 0;
        t = N - (N / 2 + 1) + 1;
        for(int i = N ; i >= t + 2 ; --i) tmp += 2 * A[i];
        tmp += A[t + 1] + A[t];
        for(int i = 1 ; i < t ; ++i) tmp -= 2 * A[i];
        res = max(res,tmp);
        out(res);enter;
    }
    else {
        int L = 1,R = N;
        int64 res = 0;
        for(int i = 1 ; i <= N - 2 ; ++i) {
            if(i & 1) res -= 2 * A[L++];
            else res += 2 * A[R--];
        }
        res += A[R] - A[L];
        out(res);enter;
    }
    return 0;
}

D - Crossing

把每一個元組之間有兩個相同元素當作惟一的連邊方式,那麼k個元組須要的邊是
\(\frac{k(k - 1)}{2}\),咱們先看N能不能解出這個k,而後構造方法就是暴力給沒連邊的元組連邊就行了code

代碼

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
//#define ivorysi
#define MAXN 100005
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
int N;
int a[1005][1005];
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(N);
    int t = 0,k = 0;
    for(int i = 1 ; i <= N ; ++i) {
        t += i;
        if(t >= N) {k = i;break;}
    }
    if(t != N) {puts("No");}
    else {
        puts("Yes");
        out(k + 1);enter;
        int cnt = 0;
        for(int j = 1 ; j <= k ; ++j) {
            for(int i = j ; i <= k ; ++i) {
                a[j][i] = ++cnt;
            }
            for(int i = j + 1 ; i <= k + 1 ; ++i) {
                a[i][j] = a[j][i - 1];
            }
        }
        for(int i = 1 ; i <= k + 1 ; ++i) {
            out(k);
            for(int j = 1 ; j <= k ; ++j) {
                space;out(a[i][j]);
            }
            enter;
        }
    }
    return 0;
}

E - Equilateral

先熟練地轉一下切比雪夫距離隊列

容易發現這個三元組必然有兩個在同一水平線或者同一豎直線上,合法的點必定是在某兩個和座標軸平行的條內,而後記錄一下轉完座標系後的矩陣和,兩兩枚舉全部水平線和豎直線上的全部點,而後計算合法的點ci

防止重複統計能夠要求同一水平線上的點的三元組第三個和任兩個不在同一豎直線,或者反過來get

代碼

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
//#define ivorysi
#define MAXN 100005
using namespace std;
typedef long long int64;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) out(x / 10);
    putchar('0' + x % 10);
}
int H,W;
char s[305][305];
int sum[605][605];
vector<int> row[605],col[605];
int Query1(int x1,int x2,int y) {
    if(x2 < x1) return 0;
    if(y < 1 || y > H + W) return 0;
    x2 = min(x2,H + W);
    x1 = max(x1,1);
    return sum[x2][y] - sum[x1 - 1][y] - sum[x2][y - 1] + sum[x1 - 1][y - 1];
}
int Query2(int x,int y1,int y2) {
    if(y2 < y1) return 0;
    if(x < 1 || x > H + W) return 0;
    y2 = min(y2,H + W);
    y1 = max(y1,1);
    return sum[x][y2] - sum[x][y1 - 1] - sum[x - 1][y2] + sum[x - 1][y1 - 1];
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(H);read(W);
    for(int i = 1 ; i <= H ; ++i) {
        scanf("%s",s[i] + 1);
    }
    for(int i = 1 ; i <= H ; ++i) {
        for(int j = 1 ; j <= W ; ++j) {
            if(s[i][j] == '#') {
                sum[i + j][i - j + W]++;
                row[i + j].pb(i - j + W);
                col[i - j + W].pb(i + j);
            }
        }
    }
    for(int i = 1 ; i <= H + W ; ++i) {
        for(int j = 1 ; j <= H + W ; ++j) {
            sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
        }
    }
    int64 ans = 0;
    for(int i = 1 ; i <= H + W ; ++i) {
        int s = row[i].size();
        sort(row[i].begin(),row[i].end());
        for(int j = 0 ; j < s ; ++j) {
            for(int k = j + 1 ; k < s ; ++k) {
                int l = row[i][k] - row[i][j];
                ans += Query2(i - l,row[i][j],row[i][k]);
                ans += Query2(i + l,row[i][j],row[i][k]);
            }
        }
    }
    for(int i = 1 ; i <= H + W ; ++i) {
        int s = col[i].size();
        sort(col[i].begin(),col[i].end());
        for(int j = 0 ; j < s ; ++j) {
            for(int k = j + 1 ; k < s ; ++k) {
                int l = col[i][k] - col[i][j];
                ans += Query1(col[i][j] + 1,col[i][k] - 1,i - l);
                ans += Query1(col[i][j] + 1,col[i][k] - 1,i + l);
            }
        }
    }
    out(ans);enter;
    return 0;
}

F - Circular

比賽的時候沒時間想了,後來把計數方案推完,我以爲這個方案真的很是假……(但我一時間沒想到反例……)
竟然A了?string

這題的英文題解貌似咕着,感受能賺一點訪問量了it

顯然若是都是1的話方案是\(n!\),這個特判掉

其次這個序列必然是相同的數都在連續的一段,不能有穿插的數,例如樣例3 1 4 1 5,很好想,不說了

而後咱們找到1所在的段長,這確定是序列進行的操做次數

爲了方便,咱們斷環爲鏈,把1扯出來做爲第一個數

而後剩下的段長都不能超過這個長度,不然輸出0

設段長爲\(len\),當前位置的數\(i\)確定是比\([i,i + len - 1]\)的最大值要大,這個你單調隊列仍是寫rmq隨意吧,都求出來,記爲\(val[i]\)

而後對於連續一段的數\([l,r]\)這個數位\(num\),這個限制了\(num\)在某個區間裏
這個區間就是\([r + 1 - len,l]\)咱們計算一下這個區間裏的數有幾個\(val[i]\)\(num\)相同,這個時候,假如這個值是0,那麼無解

統計的時候咱們記錄一個\(cnt[x]\)表示\(val[i] == x\)的個數,處理成前綴和
統計的時候枚舉每個數,假如這個數有必選位置,咱們乘上必選位置的個數,不然乘上\(cnt[i] - (i - 1)\)也就是\(cnt[i]\)\(i\)能在的位置,這些位置有且僅有\(i - 1\)個被佔用了

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
//#define ivorysi
#define MAXN 300005
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9') {
        res = res * 10 + c - '0';
        c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
        out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 998244353;
int N,a[MAXN * 2],A[MAXN],st[MAXN][20],val[MAXN],len[MAXN],must[MAXN],sum[MAXN],ql,qr,cnt[MAXN];
bool vis[MAXN];
int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
int Query(int l,int r) {
    int t = len[r - l + 1];
    return max(st[l][t],st[r - (1 << t) + 1][t]);
}
void Move(int l,int r) {
    while(qr < r) sum[val[++qr]]++;
    while(ql < l) sum[val[ql++]]--;
}
void Solve() {
    read(N);bool all_1 = 1;
    for(int i = 1 ; i <= N ; ++i) {read(a[i]);a[i + N] = a[i];if(a[i] != 1) all_1 = 0;}
    if(all_1) {
        int res = 1;
        for(int i = 1 ; i <= N ; ++i) res = mul(res,i);
        out(res);enter;return;
    }
    int s = 0;
    for(int i = 2 ; i <= 2 * N ; ++i) {
        if(a[i] == 1 && a[i - 1] != 1) {
            s = i;
            break;
        }
    }
    if(!s) {puts("0");return;}
    for(int i = 1 ; i <= N ; ++i) A[i] = a[s++];
    int p = 1;
    while(A[p] == 1) ++p;
    --p;
    int l = 0;
    for(int i = 1 ; i <= N ; ++i) {
        if(A[i] != A[i - 1]) {
            if(vis[A[i]]) {puts("0");return;}
            vis[A[i]] = 1;l = 0;
        }
        ++l;
        if(l > p) {puts("0");return;}
    }
    for(int i = 1 ; i <= N ; ++i) st[i][0] = A[i];
    for(int j = 1 ; j <= 19 ; ++j) {
        for(int i = 1 ; i <= N ; ++i) {
            if(i + (1 << j) - 1 > N) break;
            st[i][j] = max(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);
        }
    }
    for(int i = 2 ; i <= N ; ++i) len[i] = len[i / 2] + 1;
    for(int i = 1 ; i <= N ; ++i) {
        int r = min(i + p - 1,N);
        val[i] = Query(i,r);
    }
    int t = 0;ql = 1,qr = 0;
    for(int i = 1 ; i <= N ; ++i) {
        if(A[i] != A[i - 1]) {
            if(t) {
                s = max(1,i - p);
                Move(s,t);
                must[A[i - 1]] = sum[A[i - 1]];
                if(!sum[A[i - 1]]) {puts("0");return;}
            }
            t = i;
        }
    }
    s = max(1,N - p + 1);
    Move(s,t);
    must[A[N]] = sum[A[N]];
    if(!sum[A[N]]) {puts("0");return;}
    for(int i = 1 ; i <= N ; ++i) cnt[val[i]]++;
    for(int i = 1 ; i <= N ; ++i) cnt[i] += cnt[i - 1];
    int ans = 1;
    for(int i = 1 ; i <= N ; ++i) {
        if(must[i]) {ans = mul(ans,must[i]);}
        else ans = mul(ans,cnt[i] - (i - 1));
    }
    out(ans);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
相關文章
相關標籤/搜索