zoukankan      html  css  js  c++  java
  • 平时十五测

    题解:

    第一题:

    或者DP,先按x排序,dp[i]表示选择i作为结尾的最大团size;

    发现i向前连边的条件是xi - wi >= xj + wj; (这个式子我推出来,但并没有深入探究)

    简单探索一番可以发现如果i可以和前面的j连边,j可以和前面p连边,则i就可以和p连边;

    dp[i] = max(dp[j]) + 1, 这个可以用树状数组维护;

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 200005;
    int c[M<<1], dis[M<<1], q;
    struct node{int u, v, x;}p[M];
    bool cmp(node A, node B){
        return A.x < B.x;
    }
    void add(int x, int u){
        for(; x <= q; x += x&(-x)) c[x] = max(c[x], u);
    }
    int query(int x){
        int ret = 0;
        for(; x; x -= x&(-x)) ret = max(ret, c[x]);
        return ret;
    }
    int read(){
        int x = 0; int f = 1; char c = getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
        return x*=f;
    }
    
    int main(){
        freopen("clique.in","r",stdin);
        freopen("clique.out","w",stdout);
        int n = read(), tot = 0;
        for(int i = 1; i <= n; i++){
            int x = read(), w = read();
            p[i].x = x;
            p[i].u = x - w;
            p[i].v = x + w; 
            dis[++tot] = p[i].u, dis[++tot] = p[i].v;
        }
        sort(dis + 1, dis + 1 + tot);
        q = unique(dis + 1, dis + 1 + tot) - dis - 1;
        for(int i = 1; i <= n; i++){
            p[i].u = lower_bound(dis + 1, dis + 1 + q, p[i].u) - dis;
            p[i].v = lower_bound(dis + 1, dis + 1 + q, p[i].v) - dis;
        }
        sort(p + 1, p + 1 + n, cmp);
        add(p[1].v, 1);
        int ans = 1;
        for(int i = 2; i <= n; i++){
            int t = query(p[i].u);
            add(p[i].v, t+1);
            ans = max(ans, t+1);    
        }
        printf("%d
    ", ans);
        
    }
    View Code

    第二题:正确解法基于一个重要的结论,a % b <= a/2,这就意味着,任何一个数loga[i]次取模以内就能变为0。同时还注意到,a % b = a (a < b)。这两点便可以极大的降低时间复杂度。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int M = 1e5+5;
    int a[M], n, m;
    #define Ls nd->ls, lf, mid
    #define Rs nd->rs, mid+1, rg
    struct Node{
        int v; ll sum;
        Node *ls, *rs;
        void up(){
            v = max(ls->v, rs->v);
            sum = ls->sum + rs->sum;
        }
        
    }pool[M << 2], *root, *tail = pool; 
    Node *build(int lf = 1, int rg = n){
        Node *nd = ++tail;
        if(lf == rg)nd->v = nd->sum = a[lf];
        else {
            int mid = (lf + rg) >> 1;
            nd->ls = build(lf, mid);
            nd->rs = build(mid+1, rg);
            nd->up();
        }
        return nd;
    }
    void add(int pos, int x, Node *nd = root, int lf = 1, int rg = n){
        if(lf == rg){
            nd->v = nd->sum = x;
        }
        else {
            int mid = (lf + rg) >> 1;
            if(pos <= mid)add(pos, x, Ls);
            else add(pos, x, Rs);
            nd->up();
        }
    }
    
    ll query(int L, int R, Node *nd = root, int lf = 1, int rg = n){
        if(L <= lf && rg <= R)return nd->sum;
        else {
            int mid = (lf + rg) >> 1;
            ll ret = 0;
            if(L <= mid)ret += query(L, R, Ls);
            if(R > mid) ret += query(L, R, Rs);
            return ret;
        }
        
    }
    void modify(int L, int R, ll x, Node *nd = root, int lf = 1, int rg = n){
        if(nd->v < x) return ;
        if(lf == rg)nd->v %= x, nd->sum%= x;
        else {
            int mid = (lf + rg) >> 1;
            int ret = 0;
            if(L <= mid)modify(L, R, x, Ls);
            if(R > mid) modify(L, R, x, Rs);
            nd->up();
        }
    }
    int read(){
        int x = 0; int f = 1; char c = getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c<='9'&&c>='0'){x=x*10+c-'0';c=getchar();}
        return x*=f;
    }
    
    int main(){
        freopen("mod.in","r",stdin);
        freopen("mod.out","w",stdout);
        n = read(), m = read();
        for(int i = 1; i <= n; i++) a[i] = read();
        root = build();
        int opt, l, r, x;
        while(m--){
            opt = read();
            if(opt == 1){
                l = read(), r = read();
                printf("%lld
    ", query(l, r));
            }
            else if(opt == 2){
                l = read(), r = read(), x = read();
                modify(l, r, x);
            }
            else {
                l = read(), x = read();
                add(l, x);
            }
        }
        
        
    }
    View Code

    第三题:令S(i)={i+1,i+2,…,2i},f(i,k)表示S(i)中二进制下恰好有k个1的数的个数(i>0,k>=0)。

    发现f(i, k) <= f(i+1, k), 这个满足二分性质, 就二分i, f可以用数位DP解决,但是是Log^2的,我们可以直接用组合数解决;

    没有顶上界, 有C(位数,要的1), 代替数位DP的过程,顶上界只有一次,是logN的;

    #include<bits/stdc++.h>
    using namespace std;
    #define ull unsigned long long
    const ull INF = 2e18;
    ull C[67][67];
    int digit[67];
    ull dfs(int dep, int res, int sum){
        int now = sum - res;
        if(now > dep)return 0;
        if(!now)return 1;
        if(dep == 1) return digit[dep] == sum - res;
        if(!digit[dep])return dfs(dep-1, res, sum);
        ull tmp = C[dep-1][now];
        if(tmp == INF) return INF + 1;
        ull nw = dfs(dep-1, res+1, sum);
        return min(INF + 1, tmp + nw);
    }
    
    
    ull check(ull xz, ull k){
        ull up = xz<<1;
        int cnt = 0;
        while(xz){
            digit[++cnt] = xz&1;
            xz >>= 1;
        }
        ull ans1 = dfs(cnt, 0, k);
        cnt = 0;
        while(up){
            digit[++cnt] = up&1;
            up >>= 1;
        }
        ull ans2 = dfs(cnt, 0, k);
        return ans2 - ans1;
    }
    
    
    int main(){
        freopen("number.in","r",stdin);
        freopen("number.out","w",stdout);
        for(int i = 0; i <= 65; i++)
            for(int j = 0; j <= i; j++)
                if(j == 0 || i == j) C[i][j] = 1;
                else C[i][j] = min(C[i-1][j-1] + C[i-1][j], INF);
        int T;
        scanf("%d", &T);
        ull m, k;
        while(T--){
            scanf("%llu%llu", &m, &k);
            if(m == 1 && k == 1){puts("1 -1");continue;}
            ull lf = 1, rg = 1e18, p1 = -1, p2 = -1;
            while(lf <= rg){
                ull mid = (lf + rg) / 2;
                ull now = check(mid, k);
                if(now == m){
                    p1 = mid;
                    rg = mid - 1;
                }
                else if(now > m)rg = mid - 1;
                else lf = mid + 1;
            }
            
            lf = 1, rg = 2e18;
            while(lf <= rg){
                ull mid = (lf + rg) / 2;
                ull now = check(mid, k);
                if(now == m){
                    p2 = mid;
                    lf = mid + 1;
                }
                else if(now > m)rg = mid - 1;
                else lf = mid + 1;
            }
            
            printf("%llu %llu
    ", p1, p2 - p1 + 1);
        }
    }
    View Code
  • 相关阅读:
    关于struts页面跳转的问题
    java中==和equals的区别
    控制广播风暴的方法
    广播风暴的成因及解决办法
    思科FEX配置
    思科vPC技术和配置
    数据中心架构TOR和EOR
    ARP表项及老化时间
    MAC地址表和老化时间
    track 3 list boolean or
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9853176.html
Copyright © 2011-2022 走看看