zoukankan      html  css  js  c++  java
  • 【AtCoder】AGC029(A-E)

    A - Irreversible operation

    题解

    把每个B后面的W个数累加起来即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 1000005
    //#define ivorysi
    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);
    }
    
    char s[200005];
    int64 ans = 0;
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        scanf("%s",s + 1);
        int64 t = 0;
        int N = strlen(s + 1);
        for(int i = N ; i >= 1 ; --i) {
            if(s[i] == 'W') ++t;
            else ans += t;
        }
        out(ans);enter;
    }
    
    

    B - Powers of two

    题解

    这比赛打的太难受了

    这个我花了一个树结构,蒙了一个dp,然后wa了,去硬上T2

    最后发现我把一个N改成离散化后的tot就A了

    就是考虑一个点,和它组成恰好大于它的(2^{i})的值只有一个,构成了一片森林,对于每个森林从底向上更新,如果父亲和儿子能配对就尽可能多的配对

    每个(2^{i})的点若有剩余再两两配对

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 200005
    //#define ivorysi
    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);
    }
    struct node {
        int to,next;
    }E[MAXN * 10];
    map<int,int> mm;
    int val[MAXN],A[MAXN],N,tot,ans;
    int head[MAXN],sumE,dp[MAXN];
    bool vis[MAXN];
    int lowbit(int x) {
        return x & (-x);
    }
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    void Init() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) {
            read(A[i]);
            val[i] = A[i];
            mm[A[i]]++;
        }
        sort(val + 1,val + N + 1);
        tot = unique(val + 1,val + N + 1) - val - 1;
        for(int i = 1 ; i <= N ; ++i) {
            int a = val[i];
            int k = lower_bound(val + 1,val + tot + 1,a) - val;
            for(int64 t = 1 ; t <= 1073741824 ; t <<= 1) {
                if(t > 2 * a) {
                    if(mm[t - a] == 0) continue;
                    int h = lower_bound(val + 1,val + tot + 1,t - a) - val;
                    add(k,h);
                }
            }
        }
    
    }
    void dfs(int u) {
        vis[u] = 1;
        dp[u] = mm[val[u]];
        for(int i = head[u] ; i ; i = E[i].next) {
            int v = E[i].to;
            if(!vis[v]) {
                dfs(v);
                int t = min(dp[u],dp[v]);
                dp[u] -= t;
                dp[v] -= t;
                ans += t;
            }
        }
    }
    void Solve() {
        for(int i = 1 ; i <= tot ; ++i) {
            if(!vis[i]) dfs(i);
            if(lowbit(val[i]) == val[i]) ans += dp[i] / 2;
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    

    C - Lexicographic constraints

    题解

    好不容易想到了一个分段维护一个字符个数进制下的数

    没想到二分,gg了

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 200005
    //#define ivorysi
    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);
    }
    int N;
    int A[MAXN];
    int pw[MAXN][25],cnt[MAXN],ans;
    vector<pii > v;
    void Init() {
        read(N);
        for(int i = 1 ; i <= N ; ++i) read(A[i]);
        cnt[1] = 1000000000;
        for(int i = 1 ; i <= N ; ++i) {
            pw[i][0] = 1;
            for(int j = 1 ; j <= 20 ; ++j) {
                if(pw[i][j - 1]  > N / i) {
                    cnt[i] = j - 1;break;
                }
                pw[i][j] = pw[i][j - 1] * i;
            }
        }
    }
    bool check(int mid) {
        v.clear();
        v.pb(mp(A[1],0));int sum = A[1];
        for(int i = 2 ; i <= N ; ++i) {
    	if(A[i] <= A[i - 1]) {
    	    if(mid == 1) return false;
    	    if(sum < A[i - 1]) {v.pb(mp(A[i - 1] - sum,0));sum = A[i - 1];}
    	    int s = v.size() - 1;
    	    for(int k = s ; k >= 0 ; --k) {
    		if(sum - v[k].fi >= A[i]) {sum -= v[k].fi;v.pop_back();}
    		else {
    		    int t = sum - A[i];
    		    if(t > cnt[mid]) v[k].se = 0;
    		    else v[k].se /= pw[mid][t];
    		    v[k].fi -= t;
    		    sum = A[i];
    		}
    		if(sum == A[i]) break;
    	    }
    	    s = v.size() - 1;
    	    for(int k = s ; k >= 0 ; --k) {
    		if(v[k].fi <= cnt[mid]) {
    		    if(v[k].se + 1 < pw[mid][v[k].fi]) {++v[k].se;break;}
    		    else {
    			v[k].se = 0;if(k == 0) return false;
    		    }
    		}
    		else {++v[k].se;break;}
    	    }
    	}
        }
        return true;
    }
    void Solve() {
        int l = 1,r = N;
        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
        Init();
        Solve();
    }
    

    D - Grid game

    题解

    这题好水啊= =开D我就win了啊,sdC一直不过太难受了啊

    就是考虑我们肯定是走到某个障碍物上面,游戏结束了

    如何判断能不能走到呢,首先如果这一列是(j),我们所在的行(i)必须大于等于(j),如果有一个连成一串的障碍物从((j,j))开始往下压

    每次最多压了多少,就是当前列最靠下不能走的点(h),求一个(t = h - i + 1)

    (t)每次取一个前缀(max),然后对于每一列把行大于等于(j + t)的障碍物都设成不合法即可

    把每一列能走到最靠上的障碍物取一个(min)

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 200005
    //#define ivorysi
    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);
    }
    int H,W,N;
    vector<int> v[MAXN];
    bool pass[MAXN];
    void Solve() {
        read(H);read(W);read(N);
        int x,y;
        for(int i = 1 ; i <= N ; ++i) {
    	read(x);read(y);
    	v[y].pb(x);
        }
        for(int i = 1 ; i <= W ; ++i) v[i].pb(H + 1);
        sort(v[1].begin(),v[1].end());
        int ans = v[1][0] - 1;
        int t = 0;
        for(int i = 2 ; i <= W ; ++i) {
    	sort(v[i].begin(),v[i].end());
    	int s = v[i].size();
    	int m = 0;
    	for(int k = 0 ; k < s ; ++k) {
    	    if(v[i][k] <= i + t) {pass[v[i][k]] = 1;m = max(v[i][k],m);}
    	    else if(pass[v[i][k] - 1]) {pass[v[i][k]] = 1;m = max(v[i][k],m);}
    	    else {
    		ans = min(ans,v[i][k] - 1);
    		break;
    	    }
    	}
    	t = max(t,m - i + 1);
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    

    E - Wandering TKHS

    题解

    关注一下一个路径的根缀最大值

    把根缀最大值相同的部分挑出来

    我们发现一个根缀最大值是(u)(u)的某个儿子是(v)(v)中的所有节点要走到(u),就要经过(v)中所有根缀最大值为(u)的部分,这个可以差分实现

    而根缀最大值自身讨论起来有点麻烦,直接搜索即可

    代码

    #include <bits/stdc++.h>
    #define fi first
    #define se second
    #define pii pair<int,int>
    #define pdi pair<db,int>
    #define mp make_pair
    #define pb push_back
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define eps 1e-8
    #define mo 974711
    #define MAXN 200005
    //#define ivorysi
    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);
    }
    int N;
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE;
    int mv[MAXN],siz[MAXN],d[MAXN],c[MAXN],son[MAXN];
    void add(int u,int v) {
        E[++sumE].next = head[u];
        E[sumE].to = v;
        head[u] = sumE;
    }
    void calc(int u,int fa,int val) {
        son[u] = 1;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa && v < val) {
    	    calc(v,u,val);
    	    son[u] += son[v];
    	}
        }
    }
    void dfs(int u,int fa) {
        mv[u] = max(mv[fa],u);
        siz[u] = 1;
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    dfs(v,u);
    	    siz[u] += siz[v];
    	    d[u] += d[v];
    	}
        }
        if(mv[u] == u) {
    	calc(u,fa,mv[fa]);
    	d[u] = -siz[u];
        }
        if(mv[fa] == fa) d[u] += siz[u];
    }
    void dfs2(int u,int fa) {
        if(fa) {
    	if(mv[u] == u) {c[u] += son[u];}
    	else if(mv[fa] == fa) {c[u] -= son[u];c[u] += d[u];}
    	c[u] += c[fa];
        }
        for(int i = head[u] ; i ; i = E[i].next) {
    	int v = E[i].to;
    	if(v != fa) {
    	    dfs2(v,u);
    	}
        }
    }
    void Init() {
        read(N);
        int x,y;
        for(int i = 1 ; i < N ; ++i) {
    	read(x);read(y);add(x,y);add(y,x);
        }
    }
    void Solve() {
        dfs(1,0);
        dfs2(1,0);
        for(int i = 2 ; i <= N ; ++i) {
    	out(c[i]);
    	i == N ? enter : space;
        }
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Init();
        Solve();
    }
    

    F - Construction of a tree

    (2 cdot 10^{5})的网络流,有毒,不会卡常,弃疗了,再见

  • 相关阅读:
    线程池进程池
    设计原则与设计模式
    腾讯阿里第三方接入
    计划任务
    系统服务
    Python Faker模块
    Python openpyxl模块
    Python-docx模块
    进程管理
    磁盘管理
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10157002.html
Copyright © 2011-2022 走看看