• 寒假做题记录


    1/11:

       树形DP+tarjan缩环:http://codeforces.com/contest/467/problem/D

         题意是给n个字符串,再给m个转换,要求对n个字符串任意转换,使得最后n个串中r的数量最小,不区分大小写

         输出r最小能有几个,满足条件的n个串的最小长度

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e6+10, M = 1e3+20, mod = 1e9+7, inf = 2e9+10;
    
    map<string , int> mp;
    int n,cnt,m,tt = 2,b[N];
    char a[N],fi[N],se[N];
    pair<int,int > p[N],F[N],P[N];
    vector<int > G[N];
    int head[N],low[N],dfn[N],tot,top,q[N],vis[N],inq[N],scc,belong[N];
    struct ss{int to,next;}e[N * 2];
    void add(int u,int v) {
        e[tt].next = head[u];
        e[tt].to = v;
        head[u] = tt++;
    }
    void tarjan(int u) {
            dfn[u] = low[u] = ++tot;
            q[++top] = u; vis[u] = inq[u] = 1;
            for(int i = head[u]; i; i = e[i].next) {
                int to = e[i].to;
                if(!dfn[to]) {
                    tarjan(to);
                    low[u] = min(low[u],low[to]);
                } else if(inq[to]) low[u] = min(low[u],dfn[to]);
            }
            if(low[u] == dfn[u]) {
                scc++;
                do{
                    inq[q[top]] = 0;
                    belong[q[top]] = scc;
                } while(u != q[top--]);
            }
    }
    void update(int u,pair<int ,int > now) {
            if(now.first < P[u].first)
                    P[u] = now;
            else if(now.first == P[u].first && P[u].second > now.second)
                    P[u] = now;
    }
    void dfs(int u) {
        vis[u] = 1;
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(vis[to]) {
               update(u,P[to]);continue;
            }
            dfs(to);
            update(u,P[to]);
        }
    }
    int main() {
            scanf("%d",&n);
            for(int i = 1; i <= n; ++i) {
                scanf("%s",a);
                for(int j = strlen(a)-1; j >= 0; --j)
                    a[j] = a[j] >= 'A' && a[j] <= 'Z' ? (a[j] - 'A' + 'a') : a[j];
                int sum = 0;
                for(int j = strlen(a)-1; j >= 0; --j)
                    if(a[j] == 'r') sum++;
                if(!mp[a]) mp[a] = ++cnt,p[cnt] = MP(sum,strlen(a));
                b[i] = mp[a];
            }
            scanf("%d",&m);
            for(int i = 1; i <= m; ++i) {
                scanf("%s%s",fi,se);
                for(int j = strlen(fi)-1; j >= 0; --j)
                    fi[j] = fi[j] >= 'A' && fi[j] <= 'Z' ? (fi[j] - 'A' + 'a') : fi[j];
                int sum = 0,sum2 = 0;
                for(int j = strlen(fi)-1; j >= 0; --j)
                    if(fi[j] == 'r') sum++;
                for(int j = strlen(se)-1; j >= 0; --j)
                    se[j] = se[j] >= 'A' && se[j] <= 'Z' ? (se[j] - 'A' + 'a') : se[j];
                for(int j = strlen(se)-1; j >= 0; --j)
                    if(se[j] == 'r') sum2++;
                if(!mp[fi]) mp[fi] = ++cnt, p[cnt] = MP(sum,strlen(fi));
                if(!mp[se]) mp[se] = ++cnt, p[cnt] = MP(sum2,strlen(se));
                add(mp[fi],mp[se]);
            }
    
            for(int i = 1; i <= cnt; ++i) if(!dfn[i]) tarjan(i);
            for(int i = 1; i <= scc; ++i) P[i] = MP(inf,inf);
            for(int i = 1; i <= cnt; ++i)  update(belong[i],p[i]);
            for(int i = 1; i <= cnt; ++i)
                for(int j = head[i]; j; j = e[j].next)
                    if(belong[i]!=belong[e[j].to]) {
                        G[belong[i]].push_back(belong[e[j].to]);
                }
    
            memset(vis,0,sizeof(vis));
            for(int i = 1; i <= scc; ++i) {
                if(!vis[i]) dfs(i);
            }
            LL l = 0, r = 0;
            for(int i = 1; i <= n; ++i) {
                l += P[belong[b[i]]].first;
                r += P[belong[b[i]]].second;
            }
            cout<<l<<" "<<r<<endl;
            return 0;
    }
    View Code

     1/12:

      tyvj1982:http://www.tyvj.cn/p/1982 基础费用流

      HDU5647:很好的一道树DP,分析可以看http://blog.csdn.net/snowy_smile/article/details/50935295

    1/15:

      网络流24题:餐巾计划问题       费用流

      建模方法:

      每天用完的餐巾纸和要用的餐巾纸是要分开来的

      造一个源点S,Yi表示每天需要的用量,Xi表示每天用完的餐巾纸,那么S连向每一个Xi并用ri限制,每一个Yi连向T用ri限制

      每天用完的餐巾可以选择留到下一天(Xi->Xi+1),不需要花费,

      送到快洗部(Xi->Yi+m),费用为f,送到慢洗部(Xi->Yi+n),费用为s。

      每天需要的餐巾除了刚刚洗好的餐巾,还可能是新购买的(S->Yi),费用为p。

          网络流24题:负载平衡问题     费用流

      【建模分析】

      计算出每个仓库的盈余后,可以把问题转化为供求问题。

      建立供求网络,把二分图X集合中所有节点看做供应节点,Y集合所有节点看做需求节点,在能一次搬运满足供需的Xi和Yj之间连接一条费用为1的有向边,表示搬运一个单位货物费用为1。

      另外还要在Xi与相邻的Xj之间连接边,表示货物可以暂时搬运过去,不立即满足需求,费用也为1。最大流满足了所有的盈余和亏损供求平衡,最小费用就是最少搬运量。

      网络流24题:分配问题  

      HDU5644:拆点的费用流

      建模分析:先在将每个点拆成工作前(xi)工作后(yi)两点。

      不考虑休假方式:s到y1连容量为k费用0的边,yi到t连容量为p[i]费用为0的边,yi到yi+1连容量为INF费用为0的边,第P个点以后连s到yi容量为INF费用为Q的边。

      考虑休假方式:s到xi连容量为p[i]费用为0的边  表示每天能够过休假的人,xi到yi+tj连容量为INF费用为sj的边  表示休假后继续工作。

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e6+10, M = 1e3+20, mod = 1e9+7, inf = 2e9+10;
    
    int S,T,ans1;
    int P[N],m,p,Q,s,t;
    int n,k,head[40005],q[40005],dis[40005],from[40005],a[40005],cnt=1,sum,ans;
    bool inq[40005];
    struct data{int from,to,next,v,c;}e[100001];
    void ins(int u,int v,int w,int c)
    {
        cnt++;
        e[cnt].from=u;e[cnt].to=v;
        e[cnt].v=w;e[cnt].c=c;
        e[cnt].next=head[u];head[u]=cnt;
    }
    void insert(int u,int v,int w,int c)
    {ins(u,v,w,c);ins(v,u,0,-c);}
    bool spfa()
    {
        for(int i=0;i<=T;i++)dis[i]=inf;
        int t=0,w=1,i,now;
        dis[0]=q[0]=0;inq[0]=1;
        while(t!=w)
        {
            now=q[t];t++;if(t==20001)t=0;
            for(int i=head[now];i;i=e[i].next)
            {
                if(e[i].v&&dis[e[i].to]>dis[now]+e[i].c)
                {
                    from[e[i].to]=i;
                    dis[e[i].to]=dis[now]+e[i].c;
                    if(!inq[e[i].to])
                    {
                        inq[e[i].to]=1;
                        q[w++]=e[i].to;
                        if(w==20001)w=0;
                    }
                }
            }
            inq[now]=0;
        }
        if(dis[T]==inf)return 0;return 1;
    }
    void mcf()
    {
        int i,x=inf;
        i=from[T];
        while(i)
        {
            x=min(e[i].v,x);
            i=from[e[i].from];
        }
        i=from[T];
        ans1+=x;
        while(i)
        {
            e[i].v-=x;
            e[i^1].v+=x;
            ans+=x*e[i].c;
            i=from[e[i].from];
        }
    }
    int main() {
    
        int cas = 1;
        scanf("%d",&cas);
        while(cas--) {
            scanf("%d%d",&n,&k);
            S = 0 , T = 2*n+1;sum=0;
            cnt  =  1;memset(head,0,sizeof(head));
            for(int i = 1; i <= n; ++i)scanf("%d",&P[i]),sum+=P[i],insert(i+n,T,P[i],0);
            insert(S,1+n,k,0);
            scanf("%d%d%d",&m,&p,&Q);
            for(int i = p; i <= n; ++i) insert(S,i+n,inf,Q);
            for(int i = 1; i <= m; ++i){
                scanf("%d%d",&s,&t);
                for(int j = 1; j <= n; ++j) {
                    if(j+t+n<=n*2) insert(j,j+n+t,inf,s);
                }
            }
            for(int i = 1; i <= n; ++i) insert(S,i,P[i],0);
            for(int i = 1; i < n; ++i) insert(i+n,i+n+1,inf,0);
            ans = 0;ans1 = 0;
            while(spfa()) mcf();
            if(ans1 == sum)
            cout<<ans<<endl;
            else puts("No solution");
        }
        return 0;
    }
    hdu5644

    1/21:

         HDU5593 树形DP

      这是一颗固定根节点的树,要算每个点与其距离不超过k的点个数,数的办法无非向下向上数,向下数的就是基础DP,

      设定dp[i][k]表示以i为根节点向下走k步能够到达的点的个数,向上的话,由于k这么小直接暴力向上走就可以了

       这题可以分治写,待补

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 1e6+10, M = 1e3+20, mod = 1e9+7, inf = 2e9+10;
    
    int n,k,A,B;
    int dp[N][12];
    vector<int > G[N];
    void dfs(int u,int fa) {
        dp[u][0] = 1;
        for(int i = 0; i < G[u].size(); ++i) {
            int to = G[u][i];
            if(to == fa) continue;
            dfs(to,u);
            dp[u][1]+=1;
            for(int j = 2; j <= k; ++j)
                dp[u][j] += dp[to][j-1];
        }
    }
    int f[N];
    int main() {
        int T;
        scanf("%d",&T);
        while(T--) {
            scanf("%d%d%d%d",&n,&k,&A,&B);
            for(int i = 1; i <= n; ++i) G[i].clear();
            memset(f,0,sizeof(f));
            f[1] = 0;
            for(int i = 2; i <= n; ++i) {
                f[i] = (1ll*A*i%(i-1)+B)%(i-1)+1;
                G[(1ll*A*i%(i-1)+B)%(i-1)+1].push_back(i);
            }
            memset(dp,0,sizeof(dp));
            dfs(1,0);
            for(int i = 1; i <= n; ++i)
                for(int j = 1; j <= k; ++j) dp[i][j] += dp[i][j-1];
            
            for(int i = 1; i <= n; ++i) {
                int cnt = 1,tmp = i;
                while(f[tmp]&&cnt<=k) {
                    dp[i][k] += (dp[f[tmp]][k-cnt]);
                    if(k-cnt-1>=0) dp[i][k] -= dp[tmp][k-cnt-1];
                    tmp = f[tmp];
                    cnt++;
                }
            }
            int ans = 0;
            for(int i = 1; i <= n; ++i) {
                ans ^= dp[i][k];
            }
            printf("%d
    ",ans);
        }
        return 0;
    }
    HDU5593

     1/25:

         Codeforces Round #392 (Div. 2) D、E

     2/1:

      整理树链剖分

     2/6:

      CDOJ卿学姐种美丽的花:两个树状数组维护

    2/8:

      codeforces #307div.2 E.GukiZ and GukiZiana   分块+二分

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    const long long INF = 1e18+1LL;
    const double Pi = acos(-1.0);
    const int N = 5e6+10, M = 1e3+20, mod = 1e9+7, inf = 2e9+10;
    int n,q,m,block,pos[N];
    LL add[N],a[N];
    pair<LL ,int > b[N];
    void init() {
        for(int i = 1; i <= m; ++i) {
            for(int j = (i-1)*block+1; j <= min(n,i*block); ++j)
                b[j] = MP(a[j],j);
            sort(b+(i-1)*block+1, b + min(n,i*block) + 1);
        }
    }
    
    void update(int l,int r,int c) {
        if(pos[l] == pos[r]) {
                    for(int i = l; i <= r; ++i) a[i] += c;
                    for(int i = block*(pos[l]-1)+1; i <= min(pos[l]*block,n); ++i) b[i] = MP(a[i],i);
                    sort(b+block*(pos[l]-1)+1,b+min(pos[l]*block,n)+1);
            } else {
                    for(int i = pos[l]+1; i <= (pos[r]-1); ++i) add[i]+=c;
    
                    for(int i = l; i <= pos[l]*block; ++i) a[i] += c;
                    for(int i = block*(pos[l]-1)+1; i <= pos[l]*block; ++i) b[i] = MP(a[i],i);
                    sort(b+block*(pos[l]-1)+1,b+pos[l]*block+1);
    
                    for(int i = (pos[r]-1)*block+1; i <= r; ++i) a[i] += c;
                    for(int i = block*(pos[r]-1)+1; i <= min(pos[r]*block,n); ++i) b[i] = MP(a[i],i);
                    sort(b+block*(pos[r]-1)+1,b+min(pos[r]*block,n)+1);
            }
    }
    int query(LL x) {
        int mi = inf, mx = -1;
        for(int i = 1; i <= m; ++i) {
            int pos1 = lower_bound(b+(i-1)*block+1,b+min(n,i*block)+1,make_pair(x-add[i],-1)) - b;
            int pos2 = lower_bound(b+(i-1)*block+1,b+min(n,i*block)+1,MP(x-add[i]+1,-1)) - b;
            if(b[pos1].first == x-add[i] && pos1 != min(n,i*block)+1)
            {
                mi =  min(b[pos1].second,mi);
                mx = max(b[pos1].second,mx);
            }
            if(b[pos2-1].first == x-add[i]&& pos2 != (i-1)*block+1) {
                mi =  min(b[pos2-1].second,mi);
                mx = max(b[pos2-1].second,mx);
            }
        }
        if(mx == -1 || mi == inf) return -1;
        else return mx - mi;
    }
    int main() {
        scanf("%d%d",&n,&q);
        block = (int) sqrt(n);
        if(n%block) m = n/block+1;else m = n/block;
        for(int i = 1; i <= n; ++i) scanf("%I64d",&a[i]),pos[i] = (i-1)/block+1;
        init();
    
        while(q--) {
            int op,l,r;
            LL c;
            scanf("%d",&op);
            if(op == 1) {
                scanf("%d%d%I64d",&l,&r,&c);
                update(l,r,c);
            } else {
                LL x;
                scanf("%I64d",&x);
                cout<<query(x)<<endl;
            }
        }
       // for(int i = 1; i <= n; ++i) cout<<b[i].first<<" ";cout<<endl;
        return 0;
    }
    
    /*
    8 5
    1 1 1 2 1 3 1 1
    2 1
    1 1 8 1
    2 2
    1 2 5 2
    2 4
    */
    View Code

     

  • 相关阅读:
    ::before和::after伪元素的用法
    JS中map、some、every、filter方法
    C++多线程,互斥,同步
    RAII
    Proxy 代理
    Decorator 装饰
    TCP和UDP的9个区别是什么
    谈谈自己对面向对象的理解
    C++11多线程
    std::move
  • 原文地址:https://www.cnblogs.com/zxhl/p/6274045.html
Copyright © 2020-2023  润新知