zoukankan      html  css  js  c++  java
  • 【AtCoder】ARC101题解

    C - Candles

    题解

    点燃的一定是连续的一段,枚举左端点即可

    代码

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 1000005
    #define mo 999999137
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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,K;
    int64 a[100005];
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        read(N);read(K);
        for(int i = 1 ; i <= N ; ++i) {
            read(a[i]);
        }
        int64 ans = 1e16;
        for(int i = 1 ; i <= N - K + 1; ++i) {
            int t = i + K - 1;
            if(1LL * a[i] * a[t] > 0) {
                ans = min(ans,max(abs(a[i]),abs(a[t])));
            }
            else ans = min(ans,min(-2 * a[i] + a[t],2 * a[t] - a[i]));
        }
        out(ans);enter;
        return 0;
    }
    

    D - Median of Medians

    二分一个值作为中位数的中位数,把大于这个数的设成1,小于等于这个数的设成0
    然后我们就需要知道小于等于这个数做中位数的区间有多少个,用树状数组维护,和全部区间个数的一半比较一下即可

    题解

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 1000005
    #define mo 999999137
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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;
    int64 M;
    int a[100005],num[100005],cnt;
    int sum[100005][2],c[200005];
    int tr[200005];
    int lowbit(int x) {return x & -x;}
    void Insert(int x,int v) {
        while(x <= 2 * N + 1) {
            tr[x] += v;
            x += lowbit(x);
        }
    }
    int Query(int x) {
        int res = 0;
        while(x > 0) {
            res += tr[x];
            x -= lowbit(x);
        }
        return res;
    }
    bool check(int x) {
        for(int i = 1 ; i <= N ; ++i) {
            sum[i][0] = sum[i - 1][0] + (a[i] <= x);
            sum[i][1] = sum[i - 1][1] + (a[i] > x);
        }
        memset(tr,0,sizeof(tr));
        for(int i = 1 ; i <= N ; ++i) Insert(sum[i][1] - sum[i][0] + N + 1,1);
        int64 res = 0;
        for(int i = 1 ; i <= N ; ++i) {
            int t = sum[i - 1][1] - sum[i - 1][0] + N + 1;
            res += Query(t - 1);
            Insert(sum[i][1] - sum[i][0] + N + 1,-1);
        }
        return res >= M;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        read(N);
        for(int i = 1 ; i <= N ; ++i) {read(a[i]);num[i] = a[i];}
        M = 1LL * N * (N + 1) / 2;
        M = M / 2 + 1;
        sort(num + 1,num + N + 1);
        cnt = unique(num + 1,num + N + 1) - num - 1;
        int L = 1,R = cnt;
        while(L < R) {
            int mid = (L + R) >> 1;
            if(check(num[mid])) R = mid;
            else L = mid + 1;
        }
        out(num[L]);enter;
        return 0;
    }
    

    E - Ribbons on Tree

    题解

    我们用容斥来考虑,设(g(i))为至少有i条边没有被覆盖的方案数,那么答案就是
    (sum_{i = 1}^{n} (-1)^{i}g(i))考虑一边dp一边求g的系数
    用dp[u][i][0/1]表示以u为根的子树里,i个点匹配了,系数为-1或1的方案数

    转移的话用类似树背包的转移
    如果不是根的话枚举父边是不是没有被覆盖

    #include <bits/stdc++.h>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 5005
    #define mo 99994711
    #define pb push_back
    //#define ivorysi
    using namespace std;
    typedef long long int64;
    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);
    }
    const int MOD = 1000000007;
    int N;
     
    struct node {
        int to,next;
    }E[MAXN * 2];
    int head[MAXN],sumE;
    int dp[MAXN][MAXN][2],fac[MAXN],inv[MAXN],invfac[MAXN],p[MAXN],siz[MAXN],tmp[MAXN][2];
    void add(int u,int v) {
        E[++sumE].to = v;
        E[sumE].next = head[u];
        head[u] = sumE;
    }
    int mul(int a,int b) {
        return 1LL * a * b % MOD;
    }
    int inc(int a,int b) {
        return a + b >= MOD ? a + b - MOD : a + b;
    }
    void update(int &x,int y) {
        x = inc(x,y);
    }
    int C(int n,int m) {
        if(n < m) return 0;
        return mul(fac[n],mul(invfac[m],invfac[n - m]));
    }
     
    void dfs(int u,int fa) {
        dp[u][0][0] = 1;
        siz[u] = 0;
        for(int i = head[u] ; i ; i = E[i].next) {
            int v = E[i].to;
            if(v != fa) {
                dfs(v,u);
                for(int i = 0 ; i <= siz[u] + siz[v] ; ++i) tmp[i][0] = tmp[i][1] = 0;
                for(int i = 0 ; i <= siz[u] ; ++i) {
                    for(int j = 0 ; j <= siz[v] ; ++j) {
                        for(int k = 0 ; k <= 1 ; ++k) {
                            for(int h = 0 ; h <= 1 ; ++h) {
                                update(tmp[i + j][k ^ h],mul(dp[u][i][k],dp[v][j][h]));
                            }
                        }
                    }
                }
                for(int i = 0 ; i <= siz[u] + siz[v] ; ++i) {
                    dp[u][i][0] = tmp[i][0];
                    dp[u][i][1] = tmp[i][1];
                }
                siz[u] += siz[v];
            }
        }
        ++siz[u];
        if(fa) {
            for(int i = siz[u] - 1; i >= 0 ; --i) {
                for(int k = 0 ; k <= 1 ; ++k) {
                    update(dp[u][siz[u]][k],mul(dp[u][i][k ^ 1],p[siz[u] - i]));
                }
            }
        }
    }
    void Solve() {
        read(N);
        int u,v;
        for(int i = 1 ; i < N ; ++i) {
            read(u);read(v);add(u,v);add(v,u);
        }
        inv[1] = 1;
        for(int i = 2 ; i <= N ; ++i) inv[i] = mul(inv[MOD % i],MOD - MOD / i);
        fac[0] = invfac[0] = 1;
        for(int i = 1 ; i <= N ; ++i) fac[i] = mul(fac[i - 1],i),invfac[i] = mul(invfac[i - 1],inv[i]);
        p[0] = 1;
        for(int i = 1 ; i <= N ; ++i) {
            if(i & 1) p[i] = 0;
            else p[i] = mul(p[i - 2],i - 1);
        }
        dfs(1,0);
        int ans = 0;
        for(int i = 0 ; i <= N ; ++i) {
            ans = inc(ans,mul(dp[1][i][0],p[N - i]));
            ans = inc(ans,MOD - mul(dp[1][i][1],p[N - i]));
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
        return 0;
    }
    

    F - Robots and Exits

    题解

    把每个机器人到左边最近的距离记作(a_i),到右边最近的距离记作(b_i)

    我们把这个点((a_i,b_i))画在平面直角坐标系里

    然后我们记((x,y))为最左的点远离初始点x的距离,到过最右的点远离初始点y的距离
    每次可以走到((x + 1,y))((x,y + 1))
    在路径下方的点是从右边出口走的,上方的点是从左边出口走的

    我们就是要看走的折线能把点分成几个集合,用树状数组维护来转移即可

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #define enter putchar('
    ')
    #define space putchar(' ')
    #define fi first
    #define se second
    #define mp make_pair
    #define MAXN 100005
    //#define ivorysi
    #define pii pair<int,int>
    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) {putchar('-');x = -x;}
        if(x >= 10) out(x / 10);
        putchar('0' + x % 10);
    }
    const int MOD = 1000000007;
    int N,M;
    int x[MAXN],y[MAXN],tot,v[MAXN],cnt,tr[MAXN],f[MAXN];
    pii poi[MAXN];
    int lowbit(int x) {
        return x & -x;
    }
    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;
    }
    void Insert(int x,int v) {
        while(x <= cnt) {
    	tr[x] = inc(tr[x],v);
    	x += lowbit(x);
        }
    }
    int Query(int x) {
        int res = 0;
        while(x > 0) {
    	res = inc(res,tr[x]);
    	x -= lowbit(x);
        }
        return res;
    }
    void Solve() {
        read(N);read(M);
        for(int i = 1 ; i <= N ; ++i) read(x[i]);
        for(int i = 1 ; i <= M ; ++i) read(y[i]);
        int p = 1;
        for(int i = 1 ; i <= N ; ++i) {
    	while(p + 1 <= M && y[p + 1] < x[i]) ++p;
    	if(p >= M) break;
    	if(x[i] > y[p]) poi[++tot] = mp(x[i] - y[p],y[p + 1] - x[i]);
        }
        sort(poi + 1,poi + tot + 1);
        tot = unique(poi + 1,poi + tot + 1) - poi - 1;
        for(int i = 1 ; i <= tot ; ++i) {
    	v[++cnt] = poi[i].se;
        }
        v[++cnt] = 0;
        sort(v + 1,v + cnt + 1);
        cnt = unique(v + 1,v + cnt + 1) - v - 1;
        Insert(1,1);
        int ans = 1;p = 0;
        for(int i = 1 ; i <= tot ; ++i) {
    	while(p + 1 <= tot && poi[p + 1].fi < poi[i].fi) {
    	    ++p;
    	    int t = lower_bound(v + 1,v + cnt + 1,poi[p].se) - v;
    	    Insert(t,f[p]);
    	}
    	int t = lower_bound(v + 1,v + cnt + 1,poi[i].se) - v;
    	f[i] = Query(t - 1);
    	ans = inc(ans,f[i]);
        }
        out(ans);enter;
    }
    int main() {
    #ifdef ivorysi
        freopen("f1.in","r",stdin);
    #endif
        Solve();
    }
    
  • 相关阅读:
    iOS 类知乎”分页”效果的实现?
    iOS 图解弹幕功能的实现
    iOS 为何使用runtime方法交换多次后却能按照交换顺序依次执行代码逻辑?
    iOS常用算法之单链表查找倒数第n个节点(图解)
    iOS常用算法之两个有序数组合并, 要求时间复杂度为0(n)
    iOS 常用算法之设计一个算法,验证某字符是否为合法IPV4字符
    iOS .Crash文件分析处理办法 (利用symbolicatecrash工具处理)
    iOS中UIWebview中网页宽度自适应的问题
    iOS开发
    安卓应用加固之反动态调试技术总结
  • 原文地址:https://www.cnblogs.com/ivorysi/p/9775341.html
Copyright © 2011-2022 走看看