• 平时四测


    题解:

    可持久化并查集(今天早上现学习YY的, 启发式合并logN, 就不用路径压缩了, 不然会要N*logN*logN的空间)

    #include<bits/stdc++.h>
    using namespace std;
    
    const int M = 100005;
    int n, m;
    struct Node {
        int fa, siz;
        Node *ls, *rs;
    }pool[M * 32], *tail = pool, *root[M];
    
    Node * build(int lf = 1, int rg = n){
        Node *nd = ++tail;
        if(lf == rg)nd->fa = lf, nd->siz = 1;
        else{
            int mid = (lf + rg) >> 1;
            nd->ls = build(lf, mid);
            nd->rs = build(mid + 1, rg);
        }
        return nd;
    }
    #define Ls nd->ls, lf, mid
    #define Rs nd->rs, mid + 1, rg
    Node * add(int x, int fa, Node *nd, int lf = 1, int rg = n){
        Node *nnd = ++tail;
        if(lf == rg){
            nnd->fa = fa;
            nnd->siz = nd->siz;
        }
        
        else {
            int mid = (lf + rg) >> 1;
            if(x <= mid){
                nnd->rs = nd->rs;
                nnd->ls = add(x, fa, Ls);
            }
            else {
                nnd->ls = nd->ls;
                nnd->rs = add(x, fa, Rs);
            }
        }
        return nnd;
    }
    
    Node * query(int x, Node *nd, int lf = 1, int rg = n){
        if(lf == rg)return nd;
        else{
            int mid = (lf + rg) >> 1;
            if(x <= mid) return query(x, Ls);
            else return query(x, Rs);
        }
    }
    Node * kd(int x, int tt, Node *nd, int lf = 1, int rg = n){
        Node *nnd = ++tail;
        if(lf == rg)nnd->siz = tt, nnd->fa = nd->fa;
        else{
            int mid = (lf + rg) >> 1;
            if(x <= mid) {
                nnd->rs = nd->rs;
                nnd->ls = kd(x, tt, Ls);
            }
            else {
                nnd->ls = nd->ls;
                nnd->rs = kd(x, tt, Rs);
            }
        }
        return nnd;
    }
    
    Node * find(int x, Node *nd){
        Node *f = query(x, nd);
        if(f->fa == x) return f;
        return find(f->fa, nd);
    }
    
    int main(){
        freopen("build.in","r",stdin);
        freopen("build.out","w",stdout);
        scanf("%d%d", &n, &m);
        root[0] = build();
        int opt, x, y;
        int lst = 0;
        for(int i = 1; i <= m; i++){
            scanf("%d%d%d", &opt, &x, &y);
            x += lst, y += lst;
            if(opt == 1){
                Node *fx = find(x, root[i - 1]);
                Node *fy = find(y, root[i - 1]);
                if(fx->fa == fy->fa){
                    root[i] = root[i - 1];
                    continue;
                }
                int tt = fx->siz + fy->siz;
                if(fx->siz > fy->siz){    
                    root[i] = add(fy->fa, fx->fa, root[i - 1]);
                    root[i] = kd(fx->fa, tt, root[i]);
                }
                else {
                    root[i] = add(fx->fa, fy->fa, root[i - 1]);
                    root[i] = kd(fy->fa, tt, root[i]);
                    //printf("%d %d
    ", find(1, root[i])->fa, find(2, root[i])->siz);
                }
            }
            else {
                root[i] = root[i - 1];
    
                Node *ans = find(y, root[x]);
                //printf("%d
    ", ans->fa);
                lst = ans->siz;
                printf("%d
    ", lst);
            }
            //printf("%d
    ", i);
        }
    } 
    View Code

    题解的std:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    const int MAXN=100005 ;
    int n, m, fa[MAXN], times[MAXN], h[MAXN], nowT, size[MAXN];
    
    struct Info{ 
        int tm, size ;
        Info(int _tm=0,int _size=0){ tm=_tm , size=_size; }
    };
    
    vector<Info> vec[MAXN] ;
    vector<Info>::iterator it ;
    
    bool cmp(const Info &a, const Info &b){
        return a.tm < b.tm ;
    }
    
    int findFa(int a){
        if(fa[a]==a) return a;
        return findFa(fa[a]) ;
    }
    
    void mergeNodes(int u,int v){
        int fu=findFa(u), fv=findFa(v) ;  
        if(fu==fv) return ;
        if(h[fu]<h[fv]) swap(fu,fv) ;
        fa[fv]=fu, size[fu]+=size[fv], times[fv]=nowT ;
        if(h[fu]==h[fv]) h[fu]++ ;
        vec[fu].push_back(Info(nowT,size[fu])) ;
    }
    
    int query(int t, int a){
        while(a!=fa[a] && times[a]<=t) a=fa[a] ;
        it=upper_bound(vec[a].begin(),vec[a].end(),Info(t,0),cmp) ;
        --it ;
        return it->size ;
    }
    
    int main(){
        freopen("build.in","r",stdin) ;
        freopen("build.out","w",stdout) ;
        scanf("%d%d",&n,&m) ;
        for(int i=1;i<=n;++i) fa[i]=i, vec[i].push_back(Info(0,1)), h[i]=1, size[i]=1 ;
        int lastans=0 ;
        for(int i=1;i<=m;++i){
            int t, u, v ;
            nowT=i ;
            scanf("%d%d%d",&t,&u,&v) ;
            u+=lastans , v+=lastans ;
            if(t==1){
                mergeNodes(u,v) ;
            }
            else if(t==2){
                printf("%d
    ",lastans=query(u,v)) ;
            }
        }
        return 0 ;
    }
    View Code

    第二题:

    我开始想的是f[ i ]表示A的最大权值,  A用MAX去更新后面, B选的时候用MIN更新后面,这是误区1, DP一般是一种最优值;

    误区2,我是正着更新的,但实际上选下个已经和前面没有关系了, 而是一个新局面, 并且有后效性啊;

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #ifdef WIN32
    #define myLL "%I64d"
    #else
    #define myLL "%lld"
    #endif
    using namespace std;
    
    const int MAXN=1000005 ;
    int n, A[MAXN];
    long long sum[MAXN], dp[MAXN] ;
    
    int main(){
        freopen("distribute.in","r",stdin) ;
        freopen("distribute.out","w",stdout) ;
        scanf("%d",&n) ;
        for(int i=1;i<=n;++i) scanf("%d",&A[i]) ;
        for(int i=n;i>=1;--i) sum[i]=sum[i+1]+A[i] ;
        dp[n]=A[n] ;
        for(int i=n-1;i>=1;--i)
            dp[i]=max(dp[i+1], sum[i+1] - dp[i+1] + A[i]) ;
        printf(myLL"
    ", dp[1]) ;
        return 0 ;
    }
    View Code

    第三题:

    点双压边

    #include<bits/stdc++.h>
    using namespace std;
    const int M = 100005;
    
    int knum, tot, low[M], dfn[M], tag[M], tp, t[M << 1], h[M], idc, q[M << 1]; 
    bool vis[M << 1], isans[M << 1];
    
    struct edge{int v, nxt;}G[M << 1];
    void add(int u, int v){
        G[++tot].v = v, G[tot].nxt = h[u], h[u] = tot;
    }
    
    void tarjan(int u, int lst){
        dfn[u] = low[u] = ++idc;
        for(int i = h[u]; i; i = G[i].nxt){
            if((i^1) == lst) continue;
            int v = G[i].v;
            if(!vis[i]) vis[i] = vis[i^1] = 1, t[++tp] = i;
            if(!dfn[v]){
                tarjan(v, i);
                low[u] = min(low[u], low[v]);
                if(low[v] >= dfn[u]){
                    ++knum;
                    int qnum = 0, cnt = 0, s;
                    do{
                        s = t[tp--];
                        if(tag[G[s].v] != knum) tag[G[s].v] = knum, cnt++;
                        if(tag[G[s^1].v] != knum) tag[G[s^1].v] = knum, cnt++;
                        q[++qnum] = s;
                    }while(s != i);
                    if(cnt == qnum){
                        for(int i = 1; i <= qnum; i++) isans[q[i]] = isans[q[i]^1] = 1;
                    }
                }
            }
            else low[u] = min(low[u], dfn[v]);
        }
    }
    
    
    int main(){
        freopen("find.in","r",stdin);
        freopen("find.out","w",stdout);
        int n, m;
        tot++; 
        scanf("%d%d", &n, &m);
        int u, v;
        for(int i = 1; i <= m; i++){
            scanf("%d%d", &u,&v);
            add(u, v); add(v, u);
        }
        for(int i = 1; i <= n; i++)
            if(!dfn[i]) tarjan(i, 0);
        int cnt = 0;
        for(int i = 2; i <= 2*m; i+=2)
            if(isans[i]) q[++cnt] = i/2;
        if(!cnt) return !puts("0");
        printf("%d
    ", cnt);
        for(int i = 1; i <= cnt; i++) printf("%d ", q[i]);
    } 
    View Code
  • 相关阅读:
    基于MATLAB求解矩阵的正交补矩阵
    MySQL的安装与配置
    删除ubuntu后修复win7系统的引导
    VS2010中快捷添加命名空间
    java学习之函数
    java学习之break 和 continue
    For循环复杂练习
    For循环练习之99乘法表和转义字符
    java学习之语句结构
    java学习之运算符
  • 原文地址:https://www.cnblogs.com/EdSheeran/p/9690799.html
Copyright © 2020-2023  润新知