• 2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror) in codeforces(codeforces730)


    A.Toda 2

    思路:可以有二分来得到最后的数值,然后每次排序去掉最大的两个,或者3个(奇数时)。

      1 /************************************************
      2  *Author*        : Ray(siludose)
      3  *Created Time*  : 2016��10��24�� ����һ 15ʱ00��28��
      4 **Problem**      : /media/ray/708898B888987E72/Users/Administrator/Desktop/2016-2017 ACM-ICPC, NEERC, Southern Subregional Contest (Online Mirror, ACM-ICPC Rules, Teams Preferred)/erfen_a.cpp
      5 **Analyse**      : 
      6 **Get**          : 
      7 **Code**         : 
      8 *********************************************/
      9 
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <iostream>
     13 #include <algorithm>
     14 #include <vector>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <string>
     19 #include <cmath>
     20 #include <cstdlib>
     21 #include <ctime>
     22 #include <stack>
     23 using namespace std;
     24 typedef pair<int, int> pii;
     25 typedef long long ll;
     26 typedef unsigned long long ull;
     27 #define pri(a) printf("%d
    ",(a))
     28 #define xx first
     29 #define yy second
     30 const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
     31 const int maxn = 110;
     32 
     33 int a[maxn],n;
     34 
     35 struct node{
     36     int i,v;
     37 }b[maxn];
     38 vector<string> outp;
     39 bool cmp(const node &a,const node &b){
     40     return a.v>b.v;
     41 }
     42 bool check(int tar){
     43     if(tar==0)return true;
     44     for(int i=1;i<=n;i++)b[i]=(node){i,a[i]-tar};
     45     sort(b+1,b+1+n,cmp);
     46 
     47     int leftsu=0;
     48     for(int i=2;i<=n;i++)leftsu+=b[i].v;
     49     if(leftsu<b[1].v)return false;
     50     if(n==2&&(b[1].v+leftsu)%2!=0)return false;
     51     return true;
     52 }
     53 void add(int i,int j){
     54     string t;
     55     for(int i=0;i<n;i++)t+='0';
     56     t[i-1]=t[j-1]='1';
     57     outp.push_back(t);
     58 }
     59 void add(int i,int j,int k){
     60     string t;
     61     for(int i=0;i<n;i++)t+='0';
     62     t[i-1]=t[j-1]=t[k-1]='1';
     63     outp.push_back(t);
     64 }
     65 void out(int tar){
     66     printf("%d
    ",tar);
     67     if(tar==0){
     68         for(int i=1;i<n;i++)for(int j=0;j<100;j++)add(i,i+1);
     69         for(int j=0;j<100;j++)add(n,1);
     70     }else{
     71         for(int i=1;i<=n;i++)b[i]=(node){i,a[i]-tar};
     72         sort(b+1,b+1+n,cmp);
     73 
     74         int su=0;
     75         for(int i=1;i<=n;i++)su+=b[i].v;
     76 
     77         if(su%2==1){
     78             add(b[1].i,b[2].i,b[3].i);
     79             b[1].v--;b[2].v--;b[3].v--;
     80             sort(b+1,b+1+n,cmp);
     81         }
     82 
     83         while(b[1].v){
     84             add(b[1].i,b[2].i);
     85             b[1].v--;
     86             b[2].v--;
     87             sort(b+1,b+1+n,cmp);
     88         }
     89     }
     90     cout<<outp.size()<<endl;
     91     for(int i=0;i<outp.size();i++){
     92         cout<<outp[i]<<endl;
     93     }
     94 }
     95 
     96 int main(void)
     97 {
     98     scanf("%d",&n);
     99     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    100     int l=0,r=100;for(int i=1;i<=n;i++)if(a[i]<r)r=a[i];
    101     while(l<=r){
    102         int m=l+r>>1;
    103         if(check(m))l=m+1;
    104         else r=m-1;
    105     }
    106     out(r);
    107     return 0;
    108 }
    View Code

    B.Minimum and Maximum

     1 /************************************************
     2  *Author*        : Ray(siludose)
     3  *Created Time*  : 2016年10月24日 星期一 17时20分20秒
     4 **Problem**      : cf730b.cpp
     5 **Analyse**      : 
     6 **Get**          : 
     7 **Code**         : 
     8 *********************************************/
     9 
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <iostream>
    13 #include <algorithm>
    14 #include <vector>
    15 #include <queue>
    16 #include <set>
    17 #include <map>
    18 #include <string>
    19 #include <cmath>
    20 #include <cstdlib>
    21 #include <ctime>
    22 #include <stack>
    23 using namespace std;
    24 typedef pair<int, int> pii;
    25 typedef long long ll;
    26 typedef unsigned long long ull;
    27 #define pri(a) printf("%d
    ",(a))
    28 #define xx first
    29 #define yy second
    30 const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
    31 const int maxn = 1e5 + 13;
    32 
    33 bool com(int i,int j){
    34     cout<<"? "<<i<<" "<<j<<endl;
    35     char c;
    36     cin>>c;
    37     return c=='<';
    38 }
    39 int t,n;
    40 int main(void)
    41 {
    42     cin>>t;
    43     while(t--){
    44         cin>>n;
    45         int ma,mi;
    46         if(n%2==1)
    47             ma=mi=1;
    48         else
    49             if(com(1,2)) mi=1,ma=2;
    50             else mi=2,ma=1;
    51 
    52         for(int i=n%2==1?2:3;i<=n;i+=2){
    53             if(com(i,i+1)){
    54                 if(com(i,mi))mi=i;
    55                 if(com(ma,i+1))ma=i+1;
    56             }else{
    57                 if(com(i+1,mi))mi=i+1;
    58                 if(com(ma,i))ma=i;
    59             }
    60         }
    61         cout<<"! "<<mi<<" "<<ma<<endl;
    62     }
    63     return 0;
    64 }
    View Code

    C.Bulmart

    给1个n点m边简单图(可能不是联通分量),每条边一样长度(就说花费时间一样),一些边上有商店,第i个商店放ci点,有价格pi的ki个货物,q次询问,目的地gi需要ri个货物且不能花超过ai,求能否满足此询问,能的话求出最小的运送最长时间

    一开始想用网络流做的,发现其实只是取多个最小值问题就直接转问题思路。做法是对每次询问,从目的地跑bfs,把对应位置商店置一下距离,二分路程求最小路程可满足需求

    为了在找到解时直接return,预处理时商店列表以单价递增的方式排序

    这里有个问题,就是询问这里是o(qwlogn)+o(qw),1000*5000*12=6*10^7,可能1500ms不能满足,而且@Deep♂Dark♂Fantasy ,为什么你们是o(qwlogn)+o(nw)的还能过?

    补:ACdream回答是CF 1s=2~3*10^8次运算,所以能过,顺带HDU 1s=10^8次运算

      1 /************************************************
      2  *Author*        : Ray(siludose)
      3  *Created Time*  : 2016年10月25日 星期二 15时44分33秒
      4 **Problem**      : cf730c.cpp
      5 **Analyse**      :
      6 **Get**          :
      7 **Code**         :
      8 *********************************************/
      9 
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <iostream>
     13 #include <algorithm>
     14 #include <vector>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <string>
     19 #include <cmath>
     20 #include <cstdlib>
     21 #include <ctime>
     22 #include <stack>
     23 using namespace std;
     24 typedef pair<int, int> pii;
     25 typedef __int64  ll;
     26 typedef unsigned long long ull;
     27 #define pri(a) printf("%d
    ",(a))
     28 #define xx first
     29 #define yy second
     30 const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
     31 const int maxn = 5e3 + 13;
     32 
     33 int n,m;
     34 int w,u,v,q,r,g,a;
     35 vector<int> to[maxn];
     36 queue<int> que;
     37 int dist[maxn][maxn];
     38 struct St{
     39     ll c,k,p;
     40 }st[maxn];
     41 vector<struct St>tt;
     42 bool cmp(struct St a,struct St b){
     43     return a.p<b.p;
     44 }
     45 void bfs(int beg)
     46 {
     47     memset(dist[beg],-1,sizeof(dist[beg]));
     48     dist[beg][beg]=0;
     49     que.push(beg);
     50     while(!que.empty()){
     51         int te=que.front();que.pop();
     52         for(int i=0;i<to[te].size();i++){
     53             int nex=to[te][i];
     54             if(dist[beg][nex]==-1){
     55                 dist[beg][nex]=dist[beg][te]+1;
     56                 que.push(nex);
     57             }
     58         }
     59     }
     60 }
     61 bool check(int beg,int dis,int rr,int aa)
     62 {
     63     tt.clear();
     64     for(int i=1;i<=w;i++)
     65         if(dist[beg][st[i].c]<=dis&&dist[beg][st[i].c]!=-1)
     66             tt.push_back(st[i]);
     67     ll num=0,ans=0;
     68     for(int i=0;i<tt.size();i++){
     69         if((tt[i].k+num)<=rr)num+=tt[i].k,ans+=tt[i].k*tt[i].p;
     70         else ans+=(rr-num)*tt[i].p,num=rr;
     71         if(num==rr&&ans<=aa)return true;
     72     }
     73     return false;
     74 }
     75 int main(void)
     76 {
     77     scanf("%d%d",&n,&m);
     78     for(int i=1;i<=m;i++){
     79         scanf("%d%d",&u,&v);
     80         to[u].push_back(v);
     81         to[v].push_back(u);
     82     }
     83     for(int i=1;i<=n;i++){bfs(i);}
     84     scanf("%d",&w);
     85     for(int i=1;i<=w;i++)
     86         scanf("%I64d%I64d%I64d",&st[i].c,&st[i].k,&st[i].p);
     87     sort(st+1,st+1+w,cmp);
     88     scanf("%d",&q);
     89     while(q--){
     90         scanf("%d%d%d",&g,&r,&a);
     91         int ll=0,rr=n,mid,ans=-1;
     92         while(ll<=rr){
     93             mid=(ll+rr)>>1;
     94             if(check(g,mid,r,a))ans=mid,rr=mid-1;
     95             else ll=mid+1;
     96         }
     97         printf("%d
    ",ans);
     98     }
     99     return 0;
    100 }
    View Code 

    D.running over the bridge

    有n座桥,每座桥si长,人走在上面后ti秒就倒,人的速度是0.5,有无限瓶能量饮料,喝一瓶可以在r秒内变成1速度,但是只能在整数时点喝,且不能在效果持续时喝(T时喝,T+ti时可以再喝,中间不可以喝)

    xjb贪心,把喝饮料的开始时间尽量延迟,然后二分推

     1 /************************************************
     2  *Author*        : Ray(siludose)
     3  *Created Time*  : 2016年10月28日 星期五 09时48分11秒
     4 **Problem**      : cf730d.cpp
     5 **Analyse**      :
     6 **Get**          :
     7 **Code**         :
     8 *********************************************/
     9 
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <iostream>
    13 #include <algorithm>
    14 #include <vector>
    15 #include <queue>
    16 #include <set>
    17 #include <map>
    18 #include <string>
    19 #include <cmath>
    20 #include <cstdlib>
    21 #include <ctime>
    22 #include <stack>
    23 using namespace std;
    24 typedef pair<int, int> pii;
    25 typedef __int64 ll;
    26 typedef unsigned long long ull;
    27 #define pri(a) printf("%d
    ",(a))
    28 #define xx first
    29 #define yy second
    30 const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
    31 const int maxn = 2e5 + 13;
    32 
    33 ll n,r;
    34 ll l[maxn],t[maxn];
    35 queue<ll>q;
    36 int main(void)
    37 {
    38     scanf("%I64d%I64d",&n,&r);
    39     for(int i=1;i<=n;i++)scanf("%I64d",&l[i]);
    40     for(int i=1;i<=n;i++)scanf("%I64d",&t[i]);
    41     ll mt=0,ans=0,tt=0;
    42     for(int i=1;i<=n;i++){
    43         if(l[i]>t[i]){printf("-1
    ");return 0;}
    44         if(2*l[i]<=t[i]){
    45             if(mt)tt+=mt>l[i]?l[i]:l[i]*2-mt,mt=mt>l[i]?mt-l[i]:0;
    46             else tt+=l[i]*2;
    47             continue;
    48         }//don't have to jiasu
    49         ll te=2*l[i]-t[i];//need to add speed.    mt:the add rest
    50         if(mt>=te){tt+=mt>l[i]?l[i]:(l[i]*2-mt);mt=mt>l[i]?mt-l[i]:0;continue;}
    51         else if(mt!=0){tt+=mt;l[i]-=mt;t[i]-=mt;i--;mt=0;continue;}
    52         else{
    53             ll a=te/r,b=te%r;
    54             ans+=b==0?a:a+1;
    55             if(ans<=100000)
    56             for(ll j=tt+(l[i]-te)*2;j<tt+t[i];j+=r)q.push(j);
    57             tt+=l[i]*2-te; 
    58             mt=b==0?0:(a+1)*r-te;
    59         }
    60     }
    61     printf("%I64d
    ",ans);if(ans>100000)return 0;
    62     while(!q.empty()){printf("%I64d ",q.front());q.pop();}
    63     return 0;
    64 }
    View Code

    E.award ceremony

    在另外一个世界,icpc比赛的排序方式是:分数高的排位高,其次id值小的排位高。并且,最后1小时也会封榜,最后才揭晓真正排名,一个个队改变排名

    问:如何安排各个队的分数改变顺序,使排名变化次数较多?(点数最多100)

    起初我想用树状数组的方法,就是把2组状态集合到一起排序,然后每次贪心移动。

    但是一直都没法让数据与我的想法对接

    看到一些人的思路才“na ru ho do”每对点的影响都要算和,对答案贡献:点对间如果没有交叉是0,包含关系或交叉但是增减方向相反的肯定是1,交叉并且增减方向相同就是2

    这样就轻易出解了。。。白纠结那么久

     1 /************************************************
     2  *Author*        : Ray(siludose)
     3  *Created Time*  : 2016年10月29日 星期六 10时49分45秒
     4 **Problem**      : cf730e.cpp
     5 **Analyse**      : 
     6 **Get**          : 
     7 **Code**         : 
     8 *********************************************/
     9 
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <iostream>
    13 #include <algorithm>
    14 #include <vector>
    15 #include <queue>
    16 #include <set>
    17 #include <map>
    18 #include <string>
    19 #include <cmath>
    20 #include <cstdlib>
    21 #include <ctime>
    22 #include <stack>
    23 using namespace std;
    24 typedef pair<int, int> pii;
    25 typedef long long ll;
    26 typedef unsigned long long ull;
    27 #define pri(a) printf("%d
    ",(a))
    28 #define xx first
    29 #define yy second
    30 const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
    31 const int maxn = 200;
    32 
    33 struct node{
    34     int num,ran,add;
    35     bool operator < (const node &a)const{
    36         return num>a.num||(num==a.num&&ran<a.ran);
    37     }
    38 }a[maxn];
    39 int ok(int i,int j){
    40     node x=a[i],y=a[j],xx=x,yy=y;
    41     xx.num+=x.add,yy.num+=y.add;
    42     if(x<y&&yy<xx)return 1;
    43     if(y<x&&xx<yy)return 1;
    44     if(x<y&&y<xx&&xx<yy)return 2;
    45     if(y<x&&x<yy&&yy<xx)return 2;
    46     if(yy<xx&&xx<y&&y<x)return 2;
    47     if(xx<yy&&yy<x&&x<y)return 2;
    48     return 0;
    49 }
    50 int main(void)
    51 {
    52     int n,ans=0;
    53     scanf("%d",&n);
    54     for(int i=1;i<=n;i++)scanf("%d %d",&a[i].num,&a[i].add),a[i].ran=i;
    55     for(int i=1;i<=n;i++){
    56         for(int j=i+1;j<=n;j++){
    57             ans+=ok(i,j);
    58         }
    59     }
    60     printf("%d
    ",ans);
    61     return 0;
    62 }
    View Code

    F.Ber Patio

    题意:n天在饭馆吃饭,第i天花费cost(i),奖券最多使用floor(cost(i)/2),使用奖券p点,可以省p元,得到floor((a(i)-p)/10)点奖券,问如何使用可以最大化优惠

    之前一直想用o(nlogn)贪心做,从左到右,发现思路太过复杂,把优惠尽量往后推,但是发现如果用除法得到优惠点数,思路比较麻烦

    右边的不仅要加1点,要是剩余奖券积了10张还要再处理

    剩余的还要再往左遍历一遍,把最大的零头用奖券处理

    后来发现不用这么麻烦,消费请求组什么的不用看做1个数字,而是多个数据放到列表来处理

    遍历顺序也不正着来,反着来的话,可以把优惠尽量往后推

    也不用考虑剩余奖券的问题,因为昨天不能用今天可以用的奖券,直接无视,只保存消费请求

    #include<cstdio>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    int n, coin, money;
    int a[5555];
    int expire[5555];
    vector<int> fre, locked[11];
    int ans[5555];
    
    void add_fre(int amount, int id) {
        for(int i=0;i<amount;i++)
            fre.push_back(id);
    }
    
    void try_spend_fre(int &amount) {
        while(amount && fre.size()) {
            ans[fre.back()] ++;
            amount --;
            fre.pop_back();
        }
    }
    void try_spend(int &amount) {
        try_spend_fre(amount);
        for(int i=10;i>0 && amount;i--)
            while(amount && locked[i].size()) {
                amount --;
                int id = locked[i].back();
                locked[i].pop_back();
                add_fre(i, id);
                try_spend_fre(amount);
            }
    }
    
    int main() {
        scanf("%d%d", &n, &coin);
        money = 0;
        for(int i=1;i<=n;i++) {
            scanf("%d", &a[i]);
            // 先佯装全额付账,攒冥币..
            int today_coin = a[i] / 10;
            expire[i+1] = today_coin; // 今天挣了多少个币,这些币反着for时第i+1天不用就没得用了
            
            money += a[i];
        }
        
        for(int i=n;i>0;i--) {
            int today_discount = a[i]/2;
            
            // 大if出没注意!!如果第i+1天有剩余的钱,今天虽然没法花,但是相应的锁也不必加了。
            // 这个情况包含了最后一天花不出去的情况。
            int lock_fre = expire[i+1];
            
            // 付了也没法多得到冥币的零头,一开始就没锁定
            int today_fre = min(a[i]%10, today_discount);
            add_fre(today_fre, i); 
            today_discount -= today_fre;
            
            // 需要花1个冥币才能解锁的部分
            for(int j=today_discount / 10; j>0; j--)
                if (lock_fre) {
                    lock_fre --;
                    add_fre(10, i);
                } else locked[10].push_back(i);
            today_discount %= 10;
            
            if (today_discount) {
                if (lock_fre) add_fre(today_discount, i);
                else locked[today_discount].push_back(i);
            }
            
            try_spend(expire[i]); // 尝试把今天过期的币用掉
        }
        try_spend(coin);
        for(int i=1;i<=n;i++)
            money -= ans[i];
        printf("%d
    ", money);
        for(int i=1;i<=n;i++)
            printf("%d%c", ans[i], i<n ? ' ' : '
    ');
        
        return 0;
    }
    View Code

    顺带来一发未完成的

    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <bitset>
    #include <algorithm>
    #include <functional>
    #include <numeric>
    #include <utility>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <cctype>
    #include <string>
    #include <cstring>
    #include <ctime>
    #include <cstring>
    #include <fstream>
    using namespace std;
    typedef __int64 ll;
    const int N=5030;
    int min(int a,int b){return a<b?a:b;}
    int a[N],b[N];
    int main()
    {
        int n,bon,i,sum=0;
        scanf("%d%d",&n,&bon);
        for(i=0;i<n;i++)
        {
            scanf("%d",a+i);
            int lim=a[i]/2;
            int m10=(lim-a[i]%10)/10;//the most bonus*10
            if(bon<a[i]%10)b[i]=0;
            else b[i]=a[i]%10+min(m10,(bon-a[i]%10)/10)*10;
            bon-=b[i];
            if(i!=0)
            {
                while(b[i-1]>=10 && lim>=b[i]+10)
                {
                    b[i-1]-=10;
                    b[i]+=10;
                    bon++;
                    if(bon==10 && lim>=b[i]-10)
                        bon-=10,b[i]+=10;
                }
            }
            bon+=(a[i]-b[i])/10;
        }
        int proc=bon;
        bon-=(a[n-1]-b[n-1])/10;
        int min1=bon,spe=min(bon,a[n-1]/2-a[n-1]+b[n-1]);
        b[n-1]+=spe;
        bon-=spe;
        spe=0;
        for(i=n-2;i>=0;i--)
        {
            bon+=
        }
        for(i=0;i<n;i++)sum+=a[i]-b[i];
        printf("%d
    ",sum);
        for(i=0;i<n;i++)printf("%d%c",b[i],i!=n-1?' ':'
    ');
        return 0;
    }
    View Code

    G. Car Repair Shop

    #pragma warning(disable:4996)
    #include<iostream>
    #include<cstdio>
    #include <algorithm>
    #include <string.h>
    #include <queue>
    #include <vector>
    #include <stack>
    #include <set>
    #include <list>
    using namespace std;
    const int maxn = 100100;
    #define ll long long
    int main()
    {
        int n;
        scanf("%d", &n);
        int s[205], d[205];
        for (int i = 0;i < n;i++) {
            scanf("%d%d", &s[i], &d[i]);
            bool change = false;
            for (int j = 0;j < i;j++) {
                if (!((s[i] + d[i] <= s[j]) || (s[i] >= s[j] + d[j]))) {
                    if (change == false) {
                        s[i] = 1;
                        j = -1;
                        change = true;
                    }
                    else {
                        s[i] = s[j] + d[j];
                        j = -1;
                    }
                }
            }
            printf("%d %d
    ", s[i], s[i] + d[i] - 1);
        }
        return 0;
    }
    View Code

    H.Delete Them

     1 /************************************************
     2  *Author*        : Ray(siludose)
     3  *Created Time*  : 2016年10月24日 星期一 16时41分41秒
     4 **Problem**      : cf730h.cpp
     5 **Analyse**      : 
     6 **Get**          : 
     7 **Code**         : 
     8 *********************************************/
     9 
    10 #include <cstdio>
    11 #include <cstring>
    12 #include <iostream>
    13 #include <algorithm>
    14 #include <vector>
    15 #include <queue>
    16 #include <set>
    17 #include <map>
    18 #include <string>
    19 #include <cmath>
    20 #include <cstdlib>
    21 #include <ctime>
    22 #include <stack>
    23 using namespace std;
    24 typedef pair<int, int> pii;
    25 typedef long long ll;
    26 typedef unsigned long long ull;
    27 #define pri(a) printf("%d
    ",(a))
    28 #define xx first
    29 #define yy second
    30 const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
    31 const int maxn = 110;
    32 
    33 int n,m;
    34 char s[maxn][maxn];
    35 char t[maxn];
    36 int nu[maxn],len[maxn];
    37 bool vis[maxn];
    38 bool match(int v)
    39 {
    40     int c=strlen(s[v]);
    41     if(c!=len[0])return 0;
    42     for(int i=0;i<len[0];i++){
    43         if(t[i]!='?'&&t[i]!=s[v][i])return 0;
    44     }
    45     return 1;
    46 }
    47 int main(void)
    48 {
    49     scanf("%d%d",&n,&m);
    50     for(int i=0;i<n;i++)scanf("%s",s[i]);
    51     for(int i=0;i<m;i++)scanf("%d",&nu[i]),nu[i]--,vis[nu[i]]=true;
    52     for(int i=0;i<m;i++){
    53         len[i]=strlen(s[nu[i]]);
    54         if(len[i]!=len[0]){
    55             printf("No
    ");return 0;
    56         }
    57     }
    58     for(int i=0;i<len[0];i++){
    59         t[i]=s[nu[0]][i];
    60         for(int j=0;j<m;j++){
    61             if(t[i]!=s[nu[j]][i])t[i]='?';
    62         }
    63     }
    64     for(int i=0;i<n;i++)
    65         if(!vis[i])
    66             if(match(i)){
    67                 printf("No
    ");return 0;
    68             }
    69     t[len[0]]='';
    70     printf("Yes
    %s
    ",t);
    71     return 0;
    72 }
    View Code

    I.Olympiad in Programming and Sports

    思路:本题的关键在于建图,由源点连接到p点以及s点容量为p以及s,p点以及s点连接n个点,花费为a[]或者b[],再由这n个点连接汇点,然后直接跑网络模板

    当然也可以用基础值+差分化+贪心过

      1 /************************************************
      2  *Author*        : Ray(siludose)
      3  *Created Time*  : 2016年10月27日 星期四 20时17分23秒
      4 **Problem**      : cf730i_flow.cpp
      5 **Analyse**      : 
      6 **Get**          : 
      7 **Code**         : 
      8 *********************************************/
      9 
     10 #include <cstdio>
     11 #include <cstring>
     12 #include <iostream>
     13 #include <algorithm>
     14 #include <vector>
     15 #include <queue>
     16 #include <set>
     17 #include <map>
     18 #include <string>
     19 #include <cmath>
     20 #include <cstdlib>
     21 #include <ctime>
     22 #include <stack>
     23 using namespace std;
     24 typedef pair<int, int> pii;
     25 typedef long long ll;
     26 typedef unsigned long long ull;
     27 #define pri(a) printf("%d
    ",(a))
     28 #define xx first
     29 #define yy second
     30 const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
     31 const int maxn = 5e4 + 13;
     32 const int maxm=300000;
     33 struct Edge{
     34     int to,next,cap,flow,cost;
     35 }edge[maxm];
     36 int head[maxn],tol;
     37 int pre[maxn],dis[maxn];
     38 bool vis[maxn];
     39 int N;
     40 void init(int n)
     41 {
     42     N=n;
     43     tol=0;
     44     memset(head,-1,sizeof(head));
     45 }
     46 void addedge(int u,int v,int cap,int cost)
     47 {
     48     edge[tol].to=v;
     49     edge[tol].cap=cap;
     50     edge[tol].cost=cost;
     51     edge[tol].flow=0;
     52     edge[tol].next=head[u];
     53     head[u]=tol++;
     54     edge[tol].to=u;
     55     edge[tol].cap=0;
     56     edge[tol].cost=-cost;
     57     edge[tol].flow=0;
     58     edge[tol].next=head[v];
     59     head[v]=tol++;
     60 }
     61 bool spfa(int s,int t)
     62 {
     63     queue<int>q;
     64     for(int i=0;i<N;i++){
     65         dis[i]=INF;
     66         vis[i]=false;
     67         pre[i]=-1;
     68     }
     69     dis[s]=0;
     70     vis[s]=true;
     71     q.push(s);
     72     while(!q.empty()){
     73         int u=q.front();
     74         q.pop();
     75         vis[u]=false;
     76         for(int i=head[u];i!=-1;i=edge[i].next){
     77             int v=edge[i].to;
     78             if(edge[i].cap>edge[i].flow&&dis[v]>dis[u]+edge[i].cost){
     79                 dis[v]=dis[u]+edge[i].cost;
     80                 pre[v]=i;
     81                 if(!vis[v]){
     82                     vis[v]=true;
     83                     q.push(v);
     84                 }
     85             }
     86         }
     87     }
     88     if(pre[t]==-1)return false;
     89     else return true;
     90 }
     91 ll minCostMaxflow(int s,int t){
     92     ll flow=0;
     93     ll cost=0;
     94     while(spfa(s,t)){
     95         int Min=INF;
     96         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
     97             if(Min>edge[i].cap-edge[i].flow)
     98                 Min=edge[i].cap-edge[i].flow;
     99         }
    100         for(int i=pre[t];i!=-1;i=pre[edge[i^1].to]){
    101             edge[i].flow+=Min;
    102             edge[i^1].flow-=Min;
    103             cost+=edge[i].cost*Min;
    104         }
    105         flow+=Min;
    106     }
    107     return cost;
    108 }
    109 int a[maxn],b[maxn];
    110 vector<int>aa,bb;
    111 int main(void)
    112 {
    113     int n,p,s;
    114     scanf("%d%d%d",&n,&p,&s);
    115     for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    116     for(int i=1;i<=n;i++)scanf("%d",&b[i]);
    117     init(n+4);
    118     for(int i=1;i<=n;i++){
    119         addedge(0,i,1,0);
    120         addedge(i,n+1,1,-a[i]);
    121     }
    122     for(int i=1;i<=n;i++){
    123         addedge(i,n+2,1,-b[i]);
    124     }
    125     addedge(n+1,n+3,p,0);
    126     addedge(n+2,n+3,s,0);
    127     printf("%lld
    ",-minCostMaxflow(0,N-1));
    128     for (int u = 1; u <= n; u++){
    129         for(int i=head[u];i!=-1;i=edge[i].next){
    130             int v=edge[i].to;
    131             if(!edge[i].flow)continue;
    132             if(v==(n+1))aa.push_back(u);
    133             if(v==(n+2))bb.push_back(u);
    134         }
    135     }
    136     int sz=aa.size();
    137     for(int i=0;i<sz;i++)printf("%d%c",aa[i],i==(sz-1)?'
    ':' ');
    138     sz=bb.size();
    139     for(int i=0;i<sz;i++)printf("%d%c",bb[i],i==(sz-1)?'
    ':' ');
    140     return 0;
    141 }
    View Code

    J.Bottles

    给n个瓶子,容量bi剩余ai液体,在把所有液体合到最少瓶子的前提下液体转移最少,问最后有液体瓶子数量和转移液体量

    发现转移液体量就是几个瓶子剩下的液体量,可以先贪心一波把液体一起倒在容量最大的几个瓶,发现还有某些情况会让贪心失效(容量大,剩余小)

    不够这个步骤可以确定最少用几个瓶

    一开始想到搜索,有序性搜索元素。然而100个瓶子,剪枝了都不够

    计算过程发现可以把几个状态按照第几个瓶子(按容量递减剩余递减排序)总容量和实际选中瓶子数合并状态数

    然后就愉快地dp了

    /************************************************
     *Author*        : Ray(siludose)
     *Created Time*  : 2016年10月26日 星期三 19时27分49秒
    **Problem**      : cf730f.cpp
    **Analyse**      : 
    **Get**          : 
    **Code**         : 
    *********************************************/
    
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    #include <stack>
    using namespace std;
    typedef pair<int, int> pii;
    typedef long long ll;
    typedef unsigned long long ull;
    #define pri(a) printf("%d
    ",(a))
    #define xx first
    #define yy second
    const int mod = int(1e9) + 7, INF = 0x3f3f3f3f;
    const int maxn = 100 + 13;
    
    int dp[maxn][21000];
    int an[maxn][21000];
    int n,a[maxn],b[maxn];
    int main(void)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)scanf("%d",&b[i]);
        memset(dp,0x3f,sizeof(dp));
        memset(an,0x3f,sizeof(an));
        int kk=10000;dp[0][kk]=0;an[0][kk]=0;
        for(int i=1;i<=n;i++){
            for(int j=0;j<=20100;j++){
                if(dp[i][j-a[i]]>dp[i-1][j]){
                    dp[i][j-a[i]]=dp[i-1][j];
                    an[i][j-a[i]]=an[i-1][j]+a[i];
                }else if(dp[i][j-a[i]]==dp[i-1][j]){
                    an[i][j-a[i]]=min(an[i][j-a[i]],an[i-1][j]+a[i]);
                }
                if(dp[i][j+b[i]-a[i]]>dp[i-1][j]+1){
                    dp[i][j+b[i]-a[i]]=dp[i-1][j]+1;
                    an[i][j+b[i]-a[i]]=an[i-1][j];
                }else if(dp[i][j+b[i]-a[i]]==dp[i-1][j]+1){
                    an[i][j+b[i]-a[i]]=min(an[i][j+b[i]-a[i]],an[i-1][j]);
                }
            }
        }
        int ans=0x3f3f3f3f;
        int num=0x3f3f3f3f;
        for(int i=10000;i<=20100;i++){
            if(dp[n][i]<ans){
                ans=dp[n][i];num=an[n][i];
            }else if(dp[n][i]==ans){
                num=min(num,an[n][i]);
            }
        }
        printf("%d %d
    ",ans,num);
        return 0;
    }
    View Code

    K.Roads Orientation Problem

    一个联通无向图(最多400000个点,1000000条边)把所有边改成有向边,使s点为唯一源点,t为唯一汇点,且没有有向环

    唯一源点和汇点判断比较容易,从s点dfs一次求各点深度,求出dep(深度)表和fa(祖先)表,t点bfs一次,边有没走2次的就是不唯一

    难点在于如何让路径变成没有有向环

    画几个图就会发现,环上1、2条链且源点汇点属于不同树时可以构造无环路,多了会变成不唯一源点汇点

    其他类似的例如8字形的图因为不存在分叉的情况(有的话遍历2次后直接筛出来了),且有时从源点到汇点的路径不会走到与环相切的位置

    此外环上有树(或者说从源点到汇点的路径会走到与环相切的位置)会让路径一定出现有向环(2个点属于相同树)/源点汇点不唯一(2个点属于不同树)

    想到这一步就没有思路了。。。感谢codeforces的开源机制,让我理解了那些大神的做法

    碰到非树边(遍历图时边没走,目标点也没走的情况就是树边,这里是指边没走,目标点走过了)在另一个图建立映射图映射本体图

    建立映射边是建son(v)->u不是v->u

    因为可能v是源点,而画必经之路是从深度大的遍历完再走深度小的,如果v->u会因为fa[u]=-1有一些本该标记的边不会被标记

    这样如果碰到从源点到汇点的路径会走到与环相切位置的情况时,映射图的边是映射在非必经之路上的(从汇点沿fa表走不到环边),不影响结果

    没有分叉且不会走到与环相切的点,映射图的边会映射到另一条必经之路,再沿fa表走,填满另一条路

    之后遍历对应无向边,全部都是必经之路就是有解

    最后SB了,把边的数组大小开成点的数据大小,结果WA17...改了之后马上AC

    #pragma comment(linker, "/STACK:102400000,102400000")
    #include <vector>
    #include <list>
    #include <map>
    #include <set>
    #include <deque>
    #include <queue>
    #include <stack>
    #include <bitset>
    #include <algorithm>
    #include <functional>
    #include <numeric>
    #include <utility>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    #include <cctype>
    #include <string>
    #include <cstring>
    #include <cassert>
    #include <ctime>
    #include <cstring>
    #include <fstream>
    using namespace std;
    typedef __int64 ll;
    const int V=400005;
    const int E=2000005;
    int to0[E],to1[E],id0[E],id1[E],nxt0[E],nxt1[E];
    int head0[V],head1[V],cnt0,cnt1,n;
    int fa[V],son[V],dep[V],edg[V];
    bool vis[V];
    void addedge(int u,int v,int edgeid)
    {
        to0[cnt0]=v;id0[cnt0]=edgeid;nxt0[cnt0]=head0[u];head0[u]=cnt0++;
        to0[cnt0]=u;id0[cnt0]=edgeid;nxt0[cnt0]=head0[v];head0[v]=cnt0++;
    }
    
    void adde(int u,int v,int edgeid)
    {
        to1[cnt1]=v;id1[cnt1]=edgeid;nxt1[cnt1]=head1[u];head1[u]=cnt1++;
    }
    
    void dfs(int s,int depth)
    {
        //printf("
    %d",s);
        assert(depth<=n+3);
        assert(s<=n);
        vis[s]=true;
        for(int i=head0[s];i!=-1;i=nxt0[i])
        {
            int v=to0[i];
            assert(v<=n);
            if(v==fa[s])continue;
            if(!vis[v])
            {
                edg[v]=id0[i];
                dep[v]=dep[s]+1;
                son[s]=v;
                fa[v]=s;
                dfs(v,depth+1);
            }
            else if(dep[v]<dep[s])
                adde(son[v],s,id0[i]);
        }
    }
    
    pair<int,int> que[V<<1];
    int dire[E];
    
    void bfs(int t)
    {
        int tal=0,hed=0;
        queue<pair<int,int> > que;
        que.push(make_pair(t,0));
        while(!que.empty())
        {
            pair<int,int> pii=que.front();
            int u=pii.first,di=pii.second;
            que.pop();
            while(fa[u]!=-1 && dire[edg[u]]==-1)
            {
                assert(u<=n);
                dire[edg[u]]=di;
                for(int i=head1[u];i!=-1;i=nxt1[i])
                {
                    int v=to1[i];
                    assert(v<=n);
                    dire[id1[i]]=di;
                    que.push(make_pair(v,di^1));
                }
                u=fa[u];
            }
        }
    }
    
    int tu[E],tv[E];
    
    int main()
    {
        //freopen("pro.in","r",stdin);
        int T,m,s,t,i;
        scanf("%d",&T);
        while(T--)
        {
            bool flag=false;
            scanf("%d%d%d%d",&n,&m,&s,&t);
            memset(dire,-1,sizeof(int)*(m+3));
            memset(vis,0,sizeof(bool)*(n+3));
            memset(head0,-1,sizeof(int)*(n+3));cnt0=0;
            memset(head1,-1,sizeof(int)*(n+3));cnt1=0;
            for(i=0;i<m;i++)
            {
                scanf("%d%d",tu+i,tv+i);
                addedge(tu[i],tv[i],i);
            }
            dep[s]=0;fa[s]=-1;
            dfs(s,0);
            bfs(t);
            for(i=0;i<m;i++)
            {
                if(dire[i]==-1){flag=true;break;}
            }
            if(flag)puts("No");
            else
            {
                puts("Yes");
                for(i=0;i<m;i++)
                {
                    if((dep[tu[i]]<dep[tv[i]])==dire[i])tu[i]^=tv[i]^=tu[i]^=tv[i];
                    printf("%d %d
    ",tu[i],tv[i]);
                }
            }
        }
        return 0;
    }
    View Code

    L.Expression Queries

    给一段表达式,每次查询截取区间内表达式,问那段表达式的运算结果,如果不符合表达式的组成规律,输出-1

    咋看是个很难缠的线段树题,仔细一看因为不涉及修改,其实线性查询就可以解决

    左右各扫一遍,1个括号1个栈元素,不用递归,直接在构造表时推栈

    碰到左括号时升栈,碰到右括号时降栈

    至于其他3种符号就用类似于2016弱校10.3 J的处理方式

    a1表示上一个加号左边的和,a2表示上一个加号右边上一个乘号左边的积,a3表示目前的右边数字,初始a1=0 a2=1 a3=0

    碰到数字把a3*10+str[i]-'0'

    碰到乘号把a2*=a3,a3=1

    碰到加号把a1+=a2*a3,a2=1,a3=0

    查询时先看左右是否是'+' '*',左边是否')' 右边是否'('

    再匹配括号,看不同位置匹配的括号层数是否一样

    完了再组合算式出结果

    #include <cstdio>
    typedef __int64 ll;
    const int xn = 400008;
    const __int64 MOD = 1000000007;
    int
        N, Q, D,
        pb[xn], pp[xn], pm[xn],
        sb[xn], sp[xn], sm[xn],
        Lb[xn], Lp[xn], Lm[xn];
    char a[xn];
    __int64
        P10[xn], iP10[xn],
        Ab[xn], Ap[xn], Az[xn], Am[xn],
        ab[xn], ap[xn], az[xn], am[xn],
        hb[xn], hp[xn], hz[xn], hm[xn], // h?[] and t?[] are not available for i that a[i] == '+' || a[i] == '*'
        tb[xn], tp[xn], tz[xn], tm[xn];
    __int64 INV(__int64 x)
    {
        __int64 r = 1;
        for (__int64 b = MOD - 2; b; b >>= 1)
        {
            if (b & 1)
                r = r * x % MOD;
            x = x * x % MOD;
        }
        return r;
    }
    __int64 F(int l, int r)
    {
        if (a[l] == '+' || a[l] == '*' || a[l] == ')')
            return -1;
        if (a[r] == '+' || a[r] == '*' || a[r] == '(')
            return -1;
        if (sb[pb[l]] != sb[r])
            return -1;
        int lep = pp[l], rip = sp[r];
        if (sp[lep] != rip)
            return (hb[r] + tb[l] - ab[pb[l]] + MOD) % MOD;
        else
        {
            int lem = pm[l], rim = sm[r];
            if (sm[lem] != rim)
                return hz[r] + tz[l] == az[pp[l]] ? hp[r] * tp[l] % MOD * INV(ap[pp[l]]) % MOD : 0;
            else
                return (hm[r] + (tm[l] - am[pm[l]] + MOD) * iP10[rim - r - 1]) % MOD;
        }
        return 0;
    }
    int main()
    {
        scanf("%s", a + 2);
        while (a[N + 2])
            N++;
        N += 2;
        a[1] = '(', a[N] = ')';
        iP10[0] = P10[0] = 1;
        for (int i = 1,l; i <= N; i++)
        {
            P10[i] = P10[i - 1] * 10 % MOD;
            iP10[i] = iP10[i - 1] * 700000005 % MOD;
        }
        for (i = 1; i <= N; i++)
        {
            if( a[i] == ')')
            {
                ab[Lb[D]] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                ap[Lp[D]] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                az[Lp[D]] = Az[D] + !Am[D];
                am[Lm[D]] = Am[D];
            }
            pb[i] = Lb[D];
            pp[i] = Lp[D];
            pm[i] = Lm[D];
            if (a[i] == '(')
            {
                D++;
                Lb[D] = Lp[D] = Lm[D] = i;
                Az[D] = Ab[D] = Am[D] = 0;
                Ap[D] = 1;
            }
            else if (a[i] == '+')
            {
                ap[Lp[D]] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                az[Lp[D]] = Az[D] + !Am[D];
                am[Lm[D]] = Am[D];
                Lp[D] = Lm[D] = i;
                Ab[D] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                Ap[D] = 1;
                Az[D] = 0;
                Am[D] = 0;
            }
            else if (a[i] == '*')
            {
                am[Lm[D]] = Am[D];
                Lm[D] = i;
                Ap[D] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                Az[D] = Az[D] + !Am[D];
                Am[D] = 0;
            }
            else if (a[i] >= '0' && a[i] <= '9')
            {
                Am[D] = (Am[D] * 10 + a[i] - 48) % MOD;
                hb[i] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                hp[i] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                hz[i] = Az[D] + !Am[D];
                hm[i] = Am[D];
            }
            else
            {
                Am[D - 1] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                D--;
                hb[i] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                hp[i] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                hz[i] = Az[D] + !Am[D];
                hm[i] = Am[D];
            }
        }
        for (i = N, l = -1; i; i--)
        {
            if (a[i] >= '0' && a[i] <= '9')
                l++;
            else
                l = -1;
            sb[i] = Lb[D];
            sp[i] = Lp[D];
            sm[i] = Lm[D];
            if (a[i] == ')')
            {
                D++;
                Lb[D] = Lp[D] = Lm[D] = i;
                Az[D] = Ab[D] = Am[D] = 0;
                Ap[D] = 1;
            }
            else if (a[i] == '+')
            {
                Lp[D] = Lm[D] = i;
                Ab[D] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                Ap[D] = 1;
                Az[D] = 0;
                Am[D] = 0;
            }
            else if (a[i] == '*')
            {
                Lm[D] = i;
                Ap[D] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                Az[D] = Az[D] + !Am[D];
                Am[D] = 0;
            }
            else if (a[i] >= '0' && a[i] <= '9')
            {
                Am[D] = (Am[D] + P10[l] * (a[i] - 48)) % MOD;
                tb[i] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                tp[i] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                tz[i] = Az[D] + !Am[D];
                tm[i] = Am[D];
            }
            else
            {
                Am[D - 1] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                D--;
                tb[i] = (Ab[D] + (Az[D] ? 0 : Ap[D]) * Am[D]) % MOD;
                tp[i] = Ap[D] * (Am[D] ? Am[D] : 1) % MOD;
                tz[i] = Az[D] + !Am[D];
                tm[i] = Am[D];
            }
        }
        for (scanf("%d", &Q); Q--; )
        {
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%I64d
    ", F(l + 1, r + 1));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    What is the difference between the ways to implement inheritance in javascript.
    understand dojo/domReady!
    Using dijit/Destroyable to build safe Components
    Session Tracking Approaches
    difference between forward and sendredirect
    What is the DD in java web application
    棋牌游戏-后端架构(1)
    成为技术领导者笔记--领导的MOI模型
    最小表示法
    SGI STL rope
  • 原文地址:https://www.cnblogs.com/dgutfly/p/5998743.html
Copyright © 2020-2023  润新知