【AtCoder】AGC006

AGC006

A - Prefix and Suffix

……node

#include <bits/stdc++.h>
#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 eps 1e-10
#define MAXN 300005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    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;
string s,t;
void Solve() {
    read(N);
    cin >> s >> t;
    for(int i = N ; i >= 1 ; --i) {
        if(s.substr(N - i,i) == t.substr(0,i)) {
            out(2 * N - i);enter;return;
        }
    }
    out(2 * N);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

B - Median Pyramid Easy

發現若是中間有兩個目標的x那麼以後這兩個x能夠互相扶持一直到頂(事實上這也是D作題的關鍵)c++

如何造出來呢,若是x至少有一個比它小的和比它大的spa

咱們能夠中間填-1 0 1其中0在正中間,表示x,1表示一個比x大的數,-1表示一個比x小的數code

若是還有比0小的,放在1的後面,有比0大的放在-1的前面,就可讓中間兩個0了ip

剩下的隨便放就行了ci

#include <bits/stdc++.h>
#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 eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    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,x;
int a[MAXN];
vector<int> l,r;
deque<int> q;
void Solve() {
    read(N);read(x);
    if(x == 1 || x == 2 * N - 1) {puts("No");return;}
    puts("Yes");
    for(int i = 1 ; i < x ; ++i) l.pb(i);
    for(int i = x + 1 ; i <= 2 * N - 1 ; ++i) r.pb(i);
    q.pb(x);
    bool f = 0;
    while(l.size() && r.size()) {
        if(f) {
            q.push_back(l.back());
            q.push_front(r.back());
        }
        else {
            q.push_back(r.back());
            q.push_front(l.back());
        }
        l.pop_back();r.pop_back();
        f ^= 1;
    }
    if(r.size() > l.size()) swap(l,r);
    while(l.size()) {
        q.push_back(l.back());
        l.pop_back();
        q.push_front(l.back());
        l.pop_back();
    }
    for(int i = 0 ; i < 2 * N - 1 ; ++i) {out(q[i]);space;}
    enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

C - Rabbit Exercise

若是對\(x_{2}\)進行操做get

那麼就變成string

\(x_{1},x_{3} + x_{1} - x_{2},x_{3}\)it

這個須要一點想象力,以爲這種變換總須要有個不變量,或者實現了某種交換class

發現交換的是2兩邊的差分,因而問題就能夠轉化成一個映射的K次冪,最後把差分歸位就能夠恢復出最終序列了

#include <bits/stdc++.h>
#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 eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    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 x[MAXN],M,N,a[MAXN];
int64 l[MAXN],K;
struct node {
    int p[MAXN];
    friend node operator * (const node &a,const node &b) {
        node c;
        for(int i = 1 ; i < N ; ++i) c.p[i] = b.p[a.p[i]];
        return c;
    }
}f,ans;
node fpow(node x,int64 c) {
    node res,t = x;
    for(int i = 1 ; i < N ; ++i) res.p[i] = i;
    while(c) {
        if(c & 1) res = res * t;
        t = t * t;
        c >>= 1;
    }
    return res;
}
void Solve() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) read(x[i]);
    read(M);read(K);
    for(int i = 1 ; i < N ; ++i) a[i] = i;
    int t;
    for(int i = 1 ; i <= M ; ++i) {
        read(t);
        swap(a[t - 1],a[t]);
    }
    for(int i = 1 ; i < N ; ++i) f.p[a[i]] = i;
    ans = fpow(f,K);
    l[1] = x[1];
    for(int i = 1 ; i < N ; ++i) {
        l[ans.p[i] + 1] = x[i + 1] - x[i];
    }
    for(int i = 1 ; i <= N ; ++i) {
        l[i] += l[i - 1];
        out(l[i]);enter;
    }

}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

D - Median Pyramid Hard

咱們二分一個x表示答案應該小於等於x,把小於等於x的都標成0,大於x的都標成1

若是從左到右是1010101這樣的形式,即不存在相鄰兩個數值是同樣的,那麼每次取反看看中間的位置取反\(N - 1\)次是什麼就好

若是存在兩個相同的

看看哪一個相同(11或00)的離中間最近,最後的答案就是它

#include <bits/stdc++.h>
#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 eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    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,a[MAXN * 2],v[MAXN * 2];
bool check(int x) {
    for(int i = 1 ; i <= 2 * N - 1 ; ++i) {
        v[i] = (a[i] > x);
    }
    for(int i = 1 ; i < N ; ++i) {
        if(v[N - i] == v[N - i + 1]) {
            return v[N - i] != 1;
        }
        if(v[N + i] == v[N + i - 1]) {
            return v[N + i] != 1;
        }
    }
    v[N] ^= ((N - 1) & 1);
    return v[N] != 1;
}
void Solve() {
    read(N);
    for(int i = 1 ; i <= 2 * N - 1 ; ++i) read(a[i]);
    int L = 2,R = 2 * N - 2;
    while(L < R) {
        int mid = (L + R) >> 1;
        if(check(mid)) R = mid;
        else L = mid + 1;
    }
    out(L);enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

E - Rotate 3x3

發現中間一列怎麼動都還在中間的時候,就能夠考慮一下是否是和中間位置復原的交換次數有關了

由於交換一次或者當了中間軸一次,上下順序都會改變,咱們就但願交換的次數知足能讓這個數上下變成原來樣子的奇偶性

由於奇數列和偶數列不交換位置,設\(inv_{e}\)是偶數列彼此交換的位置,\(flip_{e}\)是偶數列初始時須要翻轉的位置,同理定義\(inv_{o}\)\(flip_{o}\)是奇數列的,他們的奇偶性能夠肯定

當咱們交換兩個偶數列

\(inv_{e}\)\(flip_{o}\)同時改變

當咱們交換兩個奇數列

\(inv_{o}\)\(flip_{e}\)同時改變

能夠發現\(inv_{e}\)\(flip_o\)奇偶性相等是必要的,\(inv_o\)\(flip_e\)的奇偶性是相同也是必要的

這也是充分的,咱們考慮咱們用了全部的\(inv_e\)和全部的\(inv_o\)使得第二行數所有歸位,此時\(flip_{o}\)\(flip_{e}\)都是偶數,咱們給出一種構造使得咱們能在不交換數原有順序的狀況下翻轉兩個相鄰的奇數列或偶數列

\(A\)是a列的翻轉

初始狀況是

\(a,b,c,d,e\)

\(C,B,A,d,e\)

\(C,B,E, D,a\)

\(e,b,c,D,a\)

\(e,b,A,d,C\)

\(a,B,E,d,C\)

\(a,B,c,D,e\)

\(a,d,C,b,e\)

\(c, D,A,b,e\)

\(c,B,a,d,e\)

\(A,b,C,d,e\)

這樣就能夠證實了

#include <bits/stdc++.h>
#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 eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    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,a[4][MAXN],inv[2],flip[2];
int tr[MAXN * 3];
int lowbit(int x) {return x & (-x);}
void insert(int x,int v) {
    while(x <= 3 * N) {
    tr[x] += v;
    x += lowbit(x);
    }
}
int query(int x) {
    int r = 0;
    while(x > 0) {
    r += tr[x];
    x -= lowbit(x);
    }
    return r;
}
void Solve() {
    read(N);
    for(int i = 1 ; i <= 3 ; ++i) {
    for(int j = 1 ; j <= N ; ++j) read(a[i][j]);
    }
    for(int i = 1 ; i <= N ; ++i) {
    if(a[2][i] % 3 != 2) {puts("No");return;}
    if((a[2][i] / 3 + 1 & 1) != (i & 1)) {puts("No");return;}
    int b = a[1][i],c = a[3][i];
    if(b > c) swap(b,c);
    if(b != a[2][i] - 1 || c != a[2][i] + 1) {puts("No");return;}
    if(a[2][i] - 1 == a[3][i]) flip[i & 1] ^= 1;
    }
    for(int i = 1 ; i <= N ; i += 2) {
    inv[i & 1] ^= query(3 * N) - query(a[2][i]) & 1;
    insert(a[2][i],1);
    }
    memset(tr,0,sizeof(tr));
    for(int i = 2 ; i <= N ; i += 2) {
    inv[i & 1] ^= query(3 * N) - query(a[2][i]) & 1;
    insert(a[2][i],1);
    }
    if(flip[0] != inv[1]) {puts("No");return;}
    if(flip[1] != inv[0]) {puts("No");return;}
    puts("Yes");
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

F - Blackout

一個點\((a,b)\)至關於一條邊從\(a\)\(b\)

\((a,b)\)\((b,c)\)會獲得一條邊\((c,a)\)

顯然邊只會加在一個弱連通的圖裏,咱們對每一個弱連通的圖分別處理

咱們把這張圖三色染色,若是是出邊則+1不然-1,取模3

若是三色染色能夠成功,可是圖中三個顏色並不齊,那麼這個弱連通圖加不了任何邊

若是三色染色成功了,三個顏色都齊了,那全部A能夠往全部的B連邊,全部的B能夠往全部的C連邊,全部的C能夠往全部的A連邊

若是三色染色不成功,那這個弱連通圖兩兩之間的點均可以連邊,能夠有子環

#include <bits/stdc++.h>
#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 eps 1e-10
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    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,M;
struct node {
    int to,v,next;
}E[MAXN * 2];
int head[MAXN],sumE,col[MAXN];
bool vis[MAXN];
int cnt[5];
int64 ans,s,num;
bool flag = 0;
void add(int u,int v,int c) {
    E[++sumE].to = v;
    E[sumE].next = head[u];
    E[sumE].v = c;
    head[u] = sumE;
}
void dfs(int u) {
    vis[u] = 1;++num;
    ++cnt[col[u]];
    for(int i = head[u] ; i ; i=  E[i].next) {
    int v = E[i].to;++s;
    if(vis[v]) {
        if(col[v] != (col[u] + E[i].v + 3) % 3) flag = 1;
    }
    else {
        col[v] = (col[u] + E[i].v + 3) % 3;
        dfs(v);
    }
    }
}
void Solve() {
    read(N);read(M);
    int a,b;
    for(int i = 1 ; i <= M ; ++i) {
    read(a);read(b);
    add(a,b,1);
    add(b,a,-1);
    }
    for(int i = 1 ; i <= N ; ++i) {
    if(!vis[i]) {
        memset(cnt,0,sizeof(cnt));
        col[i] = 0;
        s = 0;num = 0;
        flag = 0;dfs(i);
        if(!flag) {
        if(!cnt[0] || !cnt[1] || !cnt[2]) {
            ans += s / 2;
        }
        else {
            ans += 1LL * cnt[1] * cnt[0];
            ans += 1LL * cnt[2] * cnt[1];
            ans += 1LL * cnt[2] * cnt[0];
        }
        }
        else {
        ans += 1LL * num * num;
        }
    }
    }
    out(ans);enter;
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
相關文章
相關標籤/搜索