zoukankan      html  css  js  c++  java
  • 【AtCoder】AGC014

    AGC014

    链接

    发现两个数之间的差会逐渐缩小,所以只要不是三个数都相同,那么log次左右一定会得到答案

    #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('
    ')
    #define eps 1e-10
    #define MAXN 200005
    //#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);
    }
    int64 A,B,C,S;
    void Solve() {
        read(A);read(B);read(C);
        S = A + B + C;
        int cnt = 0;
        while(1) {
    	
    	if((A & 1) || (B & 1) || (C & 1)) {out(cnt);enter;return;}
    	if(A == B && B == C) {puts("-1");return;}
    	A = (S - A) / 2;
    	B = (S - B) / 2;
    	C = (S - C) / 2;
    	++cnt;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    B - Unplanned Queries

    直接建一个图出来,求是否每个联通块存在欧拉回路,只需要判点度就好

    #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('
    ')
    #define eps 1e-10
    #define MAXN 200005
    //#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;
    int deg[MAXN];
    void Solve() {
        read(N);read(M);
        int a,b;
        for(int i = 1 ; i <= M ; ++i) {
    	read(a);read(b);
    	++deg[a];++deg[b];
        }
        for(int i = 1 ; i <= N ; ++i) {
    	if(deg[i] & 1) {puts("NO");return;}
        }
        puts("YES");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    C - Closed Rooms

    我们发现进行完第一轮前K次随便走的操作,剩下的就是沿着最短的直线走到某个边上,因为可以用前一轮的破壁和下一轮的走路

    所以先bfs然后看看能到的所有点离边最少要再走几轮

    #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('
    ')
    #define eps 1e-10
    #define MAXN 200005
    //#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 H,W,K;
    char s[805][805];
    bool vis[805][805];
    int dis[805][805];
    queue<pii > Q;
    int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
    void Solve() {
        read(H);read(W);read(K);
        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] == 'S') {
    		Q.push(mp(i,j));vis[i][j] = 1;
    	    }
    	}
        }
        while(!Q.empty()) {
    	pii u = Q.front();Q.pop();
    	if(dis[u.fi][u.se] == K) continue;
    	for(int k = 0 ; k < 4 ; ++k) {
    	    int tx = u.fi + dx[k],ty = u.se + dy[k];
    	    if(s[tx][ty] == '.' && !vis[tx][ty]) {
    		Q.push(mp(tx,ty));
    		vis[tx][ty] = 1;
    		dis[tx][ty] = dis[u.fi][u.se] + 1;
    	    }
    	}
        }
        int ans = 1000000000;
        for(int i = 1 ; i <= H ; ++i) {
    	for(int j = 1 ; j <= W ; ++j) {
    	    if(vis[i][j]) {
    		if(i == 1 || j == 1 || i == H || j == W) ans = min(ans,1);
    		else {
    		    int t = min(i - 1,j - 1);
    		    t = min(t,min(H - i,W - j));
    		    ans = min(ans,1 + (t - 1) / K + 1);
    		}
    	    }
    	}
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    D - Black and White Tree

    dfs,如果一个点是叶子,那么认为这个地方是当这个点的父亲被占后,Aoki的必占点,标成1

    然后不是叶子的话,数数这个点Aoki的必占点有几个,如果大于等于2个,那么证明先手会赢,如果只有1个,那么这里可以变成Takahashi可以通过一定走法必占的点,如果是0个,则这个点是Aoki必占点

    如果根节点是Aoki必占点,那么先手一定会赢

    再加上某个点Aoki必占点的儿子大于等于2个情况先手会赢

    除此之外后手赢

    #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('
    ')
    #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;
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE,col[MAXN];
    bool flag = 0;
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void dfs(int u,int fa) {
        int s = 0;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    dfs(v,u);
    	    s += col[v];
    	}
        }
        if(s == 0) col[u] = 1;
        if(s >= 2) flag = 1;
    }
    void Solve() {
        read(N);
        int a,b;
        for(int i = 1 ; i < N ; ++i) {
    	read(a);read(b);
    	add(a,b);add(b,a);
        }
        dfs(1,0);
        if(col[1] || flag) puts("First");
        else puts("Second");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E - Blue and Red Tree

    我们相当于选择一条蓝边和一条红边,断开之后的两边点集是一样的

    那么我们逆着这个操作来,相当于加边,如果一个两个点之间用两条以上的边,那么就合成一个点即可

    我们把符合要求的点扔进一个队列里,然后用一个map维护点对之间的边,给每个点开一个multiset维护这个点指向的边

    启发式合并,复杂度是(O(n log^2 n))

    #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('
    ')
    #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;
    multiset<int> to[MAXN];
    map<pii,int> zz;
    queue<pii > Q;
    void insertEdge(int a,int b) {
        if(a == b) return;
        if(a > b) swap(a,b);
        zz[mp(a,b)]++;
        if(zz[mp(a,b)] == 2) Q.push(mp(a,b));
        to[a].insert(b);to[b].insert(a);
    }
    void Delete(int x,int y) {
        if(x > y) swap(x,y);
        if(zz.count(mp(x,y))) zz.erase(mp(x,y));
    }
    void Merge(int x,int y) {
        for(auto t : to[y]) {
            Delete(t,y);
            to[t].erase(to[t].find(y));
            insertEdge(t,x);
        }
    }
    void Solve() {
        read(N);
        int a,b,c,d;
        for(int i = 1 ; i < 2 * N - 1 ; ++i) {
            read(a);read(b);
            insertEdge(a,b);
        }
        for(int i = 1 ; i < N ; ++i) {
            while(1) {
                if(Q.empty()) {puts("NO");return;}
                pii u = Q.front();Q.pop();
                if(zz.count(u)) {
                    if(to[u.fi].size() < to[u.se].size()) swap(u.fi,u.se);
                    Merge(u.fi,u.se);
                    break;
                }
            }
        }
        puts("YES");
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    F - Strange Sorting

    又是一道类似数学归纳法的题

    我们看到如果删掉了1的排列如何做,如果我们排序(2,3,4...N)用了(T)次操作,那么我们找到(T - 1)次操作的时候在(2,3,4...N)这堆数最前面的数是(f)

    如果(1)(f)(2)之间,那么证明排列(1)(N)(T)次,否则用(T + 1)

    首先可以用定义看出(f eq 2),否则(T)可以是(T - 1)

    如何求(1)(f)(2)的位置关系呢,我们先证明如下两个事实

    • (f)只在排在(2...N)最前面的时候才会当高元素,否则都是矮元素
      • 第一个元素肯定是高元素,考虑一个(x)能当高元素且不为第一个,前面肯定有一个(y < x),那么(x)排不到最前面,且(x)为矮元素的时候(y)也是矮元素,然而(f)排在最前面,所以(f)当不了中间的高元素
    • (1,2,f)的循环位置不变,指((a,b,c),(b,c,a),(c,a,b))不变
      • 如果(1)是第一个数,(2)是第二个数,那么(1)是高元素,(2)是高元素,f是矮元素,顺序变为(f,1,2),循环顺序不变
      • 如果(1)是第一个数,(2)不是第二个数,(1)是高元素,(2)是矮元素,(f)是矮元素,顺序变为(2,f,1),循环顺序不变
      • 如果(2)是第一个数,(2)是高元素,(1,f)是矮元素,循环顺序不变
      • 如果(f)是第一个数,(f)是高元素,(1,2)是矮元素,循环顺序不变
      • 否则三个都是矮元素,循环顺序不变

    由此就可以求出来(f)排在最前时,(f,1,2)的位置关系

    然后边递推边求(f)即可

    #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('
    ')
    #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;
    int p[MAXN],pos[MAXN];
    int pre[MAXN],f[MAXN],ans[MAXN];
    void Solve() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {
            read(p[i]);pos[p[i]] = i;
        }
        for(int i = N - 1 ; i >= 1 ; --i) {
            if(ans[i + 1] == 0) {
                if(pos[i] < pos[i + 1]) ans[i] = 0;
                else {ans[i] = 1;f[0] = i + 1;}
            }
            else {
                int t = ans[i + 1] - 1;
                int a[3] = {i,i + 1,f[t]};
                sort(a,a + 3,[](int c,int d){return pos[c] < pos[d];});
                while(a[0] != f[t]) {
                    swap(a[2],a[0]);swap(a[1],a[2]);
                }
                if(a[1] == i) {
                    ans[i] = ans[i + 1];
                }
                else {
                    ans[i] = ans[i + 1] + 1;
                    f[t + 1] =  i + 1;
                }
            }
        }
        out(ans[1]);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    B.Icebound and Sequence
    Educational Codeforces Round 65 (Rated for Div. 2) D. Bicolored RBS
    Educational Codeforces Round 65 (Rated for Div. 2) C. News Distribution
    Educational Codeforces Round 65 (Rated for Div. 2) B. Lost Numbers
    Educational Codeforces Round 65 (Rated for Div. 2) A. Telephone Number
    Codeforces Round #561 (Div. 2) C. A Tale of Two Lands
    Codeforces Round #561 (Div. 2) B. All the Vowels Please
    Codeforces Round #561 (Div. 2) A. Silent Classroom
    HDU-2119-Matrix(最大匹配)
    读书的感想!
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10704823.html
Copyright © 2011-2022 走看看