• 18.8.27 考试总结


    这道题有dalao直接O(1)搞得 然而本蒟蒻只会二分 + 贪心

    这道题要使能够容纳的点最多 其实就是一张菊花图

    二分枚举直径长度 判断一下能够容纳的点数是否大于等于剩余的点数

    点数不够的话我们总可以通过调节链的长度总可以使他合法 就完了

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    int n,k;
    
    bool check(int len) {
        
        int del = (len - 1) / 2;
        if((ll)(n - len) <= 1LL * del * (k - 2))
            return true;
        return false;
    }
    
    void solve( ) {
        
        int l = 1,r = n,ans = n;
        while(l <= r) {
            int mid = (l + r) >> 1;
            if(check(mid)) ans = mid,r = mid - 1;
            else l = mid + 1;
        }
        printf("%d",ans - 1);
    }
    
    int main( ) {
        
        freopen("shortway.in","r",stdin);
        freopen("shortway.out","w",stdout);
        scanf("%d%d",& n,& k);
        solve( );
    }

    这道题就是一道树状数组的题 我考试的时候调了两个小时 就少了一句话 我恨

    因为可以发现e的范围很小 并且每一个小字符串都是一个个怼在上面的

    然后可以发现 对于每一个字符串的相同位置 它们模上小字符串的长度的余数都是相等的

    所以可以通过状态合并 sum[ i ][ j ][ k ][ id ]表示到了第 i 个位置 模上 j 余数为k的位置 id号字符的个数

    所以这个东西就可以通过树状数组维护

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N = 1e5 + 2;
    int sum[N][10][10][4],q,LL;
    char s[N],ss[20];
    
    int find_id(char c) {
        
        if(c == 'A') return 0;
        else if(c == 'G') return 1;
        else if(c == 'C') return 2;
        else return 3;
    }
    
    int lowbit(int a) {
        
        return a & (-a);
    }
    
    void modify(int pos,int m,int y,int id,int del) {
        
        while(pos <= LL) {
            sum[pos][m][y][id] += del;
            pos += lowbit(pos);
        }
    }
    
    void init( ) {
        
        LL = strlen(s + 1);
        for(int m = 1;m <= 10;m ++)
            for(int i = 1;i <= LL;i ++) {
                int y = i % m;
                int id = find_id(s[i]);
                modify(i,m,y,id,1);
            }
    }
    
    int query(int pos,int m,int y,int id) {
        
        int ans = 0;
        while(pos >= 1) {
            ans += sum[pos][m][y][id];
            pos -= lowbit(pos);
        }
        return ans;
    }
    
    void solve(int l,int r,int len) {
        
        int ans = 0;
        for(int i = 1;i <= len;i ++) {
            int id = find_id(ss[i]);
            int st = (l + i - 1) % len;
            int num = query(r,len,st,id) - query(l - 1,len,st,id);
            ans += num;
        }
        printf("%d
    ",ans);
    }
    
    void modify(int pos,char c) {
        
        int id_las = find_id(s[pos]),id_now = find_id(c);
        for(int m = 1;m <= 10;m ++) {
            int y = pos % m;
            modify(pos,m,y,id_las,-1);
            modify(pos,m,y,id_now, 1);
        }
        s[pos] = c;
    }
    
    int main( ) {
        
        freopen("evolution.in","r",stdin);
        freopen("evolution.out","w",stdout);
        scanf("%s",s + 1);
        init( );
        scanf("%d",& q);
        while(q --) {
            int opt;
            scanf("%d",& opt);
            if(opt == 2) {
                int l,r;
                scanf("%d%d",& l,& r);
                scanf("%s",ss + 1);
                int ll = strlen(ss + 1);
                solve(l,r,ll);
            }
            else {
                int pos;
                scanf("%d",& pos);
                scanf("%s",ss);
                modify(pos,ss[0]);
            }
        }
    }

     对于e( u , v )这条边而言 要使该边一定出现在最小生成树中 

    这条边的边权就一定要小于所有能够除了该边之外连通u v两个点的链上的最大值的最小的那个

    也就是小于u v两个点在最小生成树上的路径中的最大值

    所以这条边可能会出现两种情况

    1.非树边 

         

    根据最小生成树的性质可以知道 对于虚线 它的答案就是浅灰色边中的最大值 - 1

    2.树边

    对于红色这条边 要使他出现在最小生成树中 那么他一定是连接两个连通块中所有边的最小值

    也就是说它小于所有黄色边 那么怎么实现这个东西呢

    每次遇到黄色边 就将它的两个端点在树上的路径权值分别与它的值取min(初值赋正无穷)

    (因为连接这两个连通块的边在树上的路径一定经过红边) 所以就达到了取min的效果

    算法就是mst... 这道题真的代码量好大 改了半天cnm

    代码

    #include <bits/stdc++.h>
    #define oo 1e9
    using namespace std;
    
    const int N = 1e6 + 5;
    int n,fa[N],fat[N],tot,nex[2 * N],tov[2 * N],ntot,nex1[2 * N];
    int head1[N],val[2 * N],val1[2 * N],tov1[2 * N],head[N],co[2 * N];
    int m,size[N],son[N],in[N],out[N],seq[N],dep[N],top[N],idc,f[2 * N];
    int f1[4 * N],tag[4 * N],ans[N];
    bool isnot[N];
    struct edge {
        
        int u,v,w,id;
    }e[N];
    
    bool cmp(const edge & a,const edge & b) {
        return a.w < b.w;
    }
    
    int find_fa(int u) {
        
        if(u == fa[u]) return u;
        return fa[u] = find_fa(fa[u]);
    }
    
    void init( ) {
        for(int i = 1;i <= n;i ++) fa[i] = i;
    }
    
    void add(int u,int v,int w) {
        
        tot ++;
        nex[tot] = head[u];
        tov[tot] = v;
        head[u] = tot;
        co[tot] = w;
    }
    
    void add1(int u,int v) {
        
        ntot ++;
        nex1[ntot] = head1[u];
        tov1[ntot] = v;
        val1[ntot] = oo;
        head1[u] = tot;
    }
    
    void build( ) {
        
        for(int i = 1;i <= m;i ++) {
            int u = e[i].u,v = e[i].v;
            int fa1 = find_fa(u),fa2 = find_fa(v);
            if(fa1 == fa2) {
                isnot[e[i].id] = true;
                continue;
            }
            else {
                fa[fa2] = fa1;
                add(u,v,e[i].w); add(v,u,e[i].w);
            }
        }
    }
    
    void dfs1(int u,int fa) {
        
        size[u] = 1;
        fat[u] = fa;
        for(int i = head[u];i;i = nex[i]) {
            int v = tov[i];
            if(v == fa) continue;
            dep[v] = dep[u] + 1;
            dfs1(v,u);
            val[v] = co[i];
            size[u] += size[v];
            if(size[v] > size[son[u]]) son[u] = v;
        }
    }
    
    void dfs2(int u,int tp) {
        
        top[u] = tp;
        idc ++; in[u] = idc;
        seq[idc] = u;
        if(son[u]) dfs2(son[u],tp);
        for(int i = head[u];i;i = nex[i]) {
            int v = tov[i];
            if(v == fat[u] || v == son[u]) continue;
            dfs2(v,v);
        }
    }
    
    void update(int o) {
        f[o] = max(f[2 * o],f[2 * o + 1]);
    }
    
    void build_tree1(int o,int l,int r) {
        
        if(l == r) {
            f[o] = val[seq[l]];
            return ;
        }
        int mid = (l + r) >> 1;
        build_tree1(2 * o,l,mid);
        build_tree1(2 * o + 1,mid + 1,r);
        update(o);
    }
    
    int query_tree(int o,int l,int r,int L,int R) {
        
        if(l >= L && r <= R) {
            return f[o];
        }
        int mid = (l + r) >> 1;
        int ans = 0;
        if(L <= mid) ans = query_tree(2 * o,l,mid,L,R);
        if(mid < R) ans = max(ans,query_tree(2 * o + 1,mid + 1,r,L,R));
        return ans;
    }
    
    int query(int u,int v) {
        
        int ans = 0;
        while(top[u] != top[v]) {
            if(dep[top[u]] < dep[top[v]]) swap(u,v);
            int cmp = query_tree(1,1,idc,in[top[u]],in[u]);
            ans = max(ans,cmp);
            u = fat[top[u]];
         }
         if(dep[u] < dep[v]) swap(u,v);
         ans = max(ans,query_tree(1,1,idc,in[v] + 1,in[u]));
         return ans;
    }
    
    void push_down(int o) {
        
        if(tag[o]) {
            if(tag[2 * o]==0) tag[2 * o] = tag[o];
            else
            tag[2 * o] = min (tag[2 * o],tag[o]);
            if(tag[2 * o + 1]==0) tag[2 * o + 1] = tag[o];
            else
            tag[2 * o + 1] = min (tag[2 * o + 1],tag[o]);
            f1[2 * o] = min(f1[2 * o],tag[o]);
            f1[2 * o + 1] = min(f1[2 * o + 1],tag[o]);
            tag[o] = 0;
        }
    }
    
    void modify(int o,int l,int r,int L,int R,int w) {
        
        if(l >= L && r <= R) {
            f1[o] = min(f1[o],w - 1);
            if(tag[o]==0) tag[o] = w - 1;
            else 
              tag[o] = min(w - 1,tag[o]);
            return ;
        }
        push_down(o);
        int mid = (l + r) >> 1;
        if(L <= mid) modify(2 * o,l,mid,L,R,w);
        if(mid < R)  modify(2 * o + 1,mid + 1,r,L,R,w);
    }
    
    void modify_tr2(int u,int v,int w) {
        
        while(top[u] != top[v]) {
            if(dep[top[u]] < dep[top[v]]) swap(u,v);
            modify(1,1,idc,in[top[u]],in[u],w);
            u = fat[top[u]];
        }
        if(dep[u] < dep[v]) swap(u,v);
         modify(1,1,idc,in[v] + 1,in[u],w);
    }
    
    int query_tr2(int o,int l,int r,int pos) {
        
        if(l == r) {
            return f1[o];
        }
        push_down(o);
        int mid = (l + r) >> 1;
        if(pos <= mid) return query_tr2(2 * o,l,mid,pos);
        else return query_tr2(2 * o + 1,mid + 1,r,pos);
    }
    
    int main( ) {
        
        freopen("mst.in","r",stdin);
        freopen("mst.out","w",stdout);
        scanf("%d%d",& n,& m);
        init( );
        for(int i = 1;i <= m;i ++) {
            int u,v,w;
            scanf("%d%d%d",& u,& v,& w);
            e[i].u = u; e[i].v = v;
            e[i].w = w; e[i].id = i;
        }
        memset(tag,0x3f3f3f,sizeof(tag));
        memset(f1,0x3f3f3f,sizeof(f1));
        int p = f1[0];
        dep[1] = 1;
        sort(e + 1,e + m + 1,cmp);
        build( );
        dfs1(1,1); dfs2(1,1);
        build_tree1(1,1,idc);
        for(int i = 1;i <= m;i ++) {
            int fu = e[i].id;
            if(isnot[fu]) {
                ans[fu] = query(e[i].u,e[i].v) - 1;
                modify_tr2(e[i].u,e[i].v,e[i].w);
            }
        }
        for(int i = 1;i <= m;i ++) {
            int fu = e[i].id;
            if(! isnot[fu]) {
                int u = dep[e[i].u] > dep[e[i].v] ? e[i].u : e[i].v;
                ans[fu] = query_tr2(1,1,idc,in[u]);
                if(ans[fu] == p) ans[fu] = -1; 
            }
        }
        for(int i = 1;i <= m;i ++) printf("%d ",ans[i]);
    }
  • 相关阅读:
    splinter webdriver API 的基本实现
    201253 线程和进程的区别
    Winform中的默认图片
    [收藏】正确使用SqlConnection对象,兼谈数据库连接池
    手机相关的基础名称
    常见排序
    SIP相关内容
    How to set the WIFI configuration
    本地化的设置和读取
    Serialize And Deserialize Binary Tree
  • 原文地址:https://www.cnblogs.com/Rubenisveryhandsome/p/9544943.html
Copyright © 2020-2023  润新知