2016-2017 ACM-ICPC Northeastern European Regional Contest (NEERC 16)

A:模拟

注意各种情况和细节~

 1 #include<cstdio>
 2 #include<string>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 
 7 using namespace std;
 8 
 9 char s[200];
10 char now[200];
11 
12 int check(int pos){
13     int flag=-1;
14     while(s[pos]>='a' && s[pos]<='z' || s[pos]>='A' && s[pos]<='Z'){
15         flag=0;
16         if(s[pos]>='a' && s[pos]<='z') pos++;
17         else return -1;
18     }
19     if(flag<0) return flag;
20     return pos;
21 }
22 
23 int main(){
24     freopen("abbreviation.in","r",stdin);
25     freopen("abbreviation.out","w",stdout);
26     int n=0;
27     while(gets(s)){
28         int len=strlen(s),flag=1,pos=0;
29         for(int i=0;i<len;i++){
30             if(flag==1 && s[i]>='A' && s[i]<='Z'){
31                 now[++pos]=s[i];
32                 int f=check(i+1);
33                 if(f==-1) printf("%c",s[i]),flag=2;
34                 else{
35                     int tmp=1;
36                     while(tmp!=-1 && s[f]==' ' && s[f+1]>='A' && s[f+1]<='Z'){
37                         tmp=check(f+2);
38                         if(tmp!=-1) now[++pos]=s[f+1],f=tmp;
39                     }
40                     if(pos>=2){
41                         for(int j=1;j<=pos;j++) printf("%c",now[j]);
42                         pos=0;
43                         printf(" (");
44                         for(int j=i;j<=f-1;j++) printf("%c",s[j]);
45                         printf(")");
46                         i=f; if(i!=len) printf("%c",s[i]);
47                     }
48                     else printf("%c",s[i]);
49                     flag=1;
50                 }
51                 pos=0;
52             }
53             else if(!(s[i]>='A' && s[i]<='Z' || s[i]>='a' && s[i]<='z')) printf("%c",s[i]),flag=1;
54             else printf("%c",s[i]),flag=2;
55         }
56         puts("");
57     }    
58     return 0;
59 }
View Code

B:字典树+2-sat

用字典树求出字符串之间的关系辅助构图,之后用2-sat即可。

  1 include<bits/stdc++.h>
  2 
  3 #define maxn 500000+5 
  4 #define maxm 4000000+5 
  5 
  6 using namespace std;
  7 
  8 vector<char>c[maxn];
  9 vector<int>a[maxn<<1],g[maxm];
 10 int num,nx[maxn<<1][2],w[maxn<<1],w2[maxn<<1],pos[maxn],pr[maxn<<1],sf[maxn<<1];
 11 int n,m,p,l,root=1;
 12 char s[maxn];
 13 
 14 inline void Insert(int& x,int y,int z){
 15     if(!x) x=++num;
 16     if(y==l){
 17         a[x].push_back(z);
 18         return;
 19     }
 20     Insert(nx[x][s[y]-'0'],y+1,z);
 21 }
 22 
 23 inline void Build(int x,int y,int z){
 24     if(!x) return;
 25     int X=++num,Y=++num;
 26     if(a[x].size()==0){
 27         pr[x]=X;sf[x]=Y;
 28     }
 29     else{
 30         pr[x]=++num;sf[x]=++num;
 31         for(int i=0;i<a[x].size();i++){
 32             w[a[x][i]]=++num;
 33             g[num].push_back(a[x][i]^1);
 34             if(!i) g[pr[x]].push_back(num);
 35             else g[w[a[x][i-1]]].push_back(num);
 36             if(i==(int)a[x].size()-1) g[num].push_back(X);
 37             w2[a[x][i]]=++num; g[num].push_back(a[x][i]^1);
 38         }
 39         for(int i=0;i<a[x].size();i++){
 40             if(i==(int)a[x].size()-1) g[Y].push_back(w2[a[x][i]]),g[a[x][i]].push_back(X);
 41             else g[a[x][i]].push_back(w[a[x][i+1]]),g[w2[a[x][i+1]]].push_back(w2[a[x][i]]);
 42             if(!i) g[w2[a[x][i]]].push_back(sf[x]),g[a[x][i]].push_back(sf[x]);else g[a[x][i]].push_back(w2[a[x][i-1]]);
 43         }
 44     }
 45     if(y) g[y].push_back(pr[x]),g[sf[x]].push_back(z);
 46     Build(nx[x][0],X,Y); Build(nx[x][1],X,Y);
 47 }
 48 
 49 bool b[maxm];
 50 int cnt;
 51 int f[maxm],dfn[maxm],low[maxm],T,st[maxm],top;
 52 
 53 inline void Dfs(int x){
 54     dfn[x]=low[x]=++T;st[++top]=x;
 55     for(int i=0;i<g[x].size();i++){
 56         int v=g[x][i];
 57         if(!dfn[v]) Dfs(v),low[x]=min(low[x],low[v]);else
 58         if(!f[v]) low[x]=min(low[x],dfn[v]);
 59     }
 60     if(low[x]==dfn[x]){
 61         ++cnt;
 62         while(st[top]!=x) f[st[top--]]=cnt;
 63         f[st[top--]]=cnt;
 64     }
 65 }
 66 
 67 bool Tarjan(){
 68     for(int i=2;i<=num;i++)
 69         if(!dfn[i])Dfs(i);
 70     for(int i=1;i<=n;i++)
 71         if(f[i<<1]==f[i<<1|1]) return 0;
 72     return 1;
 73 }
 74 
 75 int main(){
 76     freopen("binary.in","r",stdin);
 77     freopen("binary.out","w",stdout);
 78     scanf("%d",&n);
 79     memset(pos,-1,sizeof(pos));num=n<<1|1;
 80     for(int i=1;i<=n;i++){
 81         scanf("%s",s);l=strlen(s);
 82         for(int j=0;j<l;j++){
 83             if(s[j]=='?')pos[i]=j;
 84             c[i].push_back(s[j]);
 85         }
 86         if(pos[i]==-1)Insert(root,0,i<<1|1),g[i<<1].push_back(i<<1|1);else{
 87             s[pos[i]]='0';Insert(root,0,i<<1|1);
 88             s[pos[i]]='1';Insert(root,0,i<<1);
 89         }
 90     }
 91     Build(1,0,0);
 92     if(!Tarjan()) puts("NO");
 93     else{
 94         puts("YES");
 95         for(int i=1;i<=n;i++){
 96             for(int j=0;j<c[i].size();j++)
 97             if(c[i][j]=='?')putchar((f[i<<1]<f[i<<1|1])+'0');else putchar(c[i][j]);
 98             putchar('\n');
 99         }
100     }
101     return 0;
102 }
View Code

D:上下界费用流

将每个点和每个长度D的区间看作边,限制条件看作流量上下界,差分建图,无源汇最大费用费用流,非常巧妙的使用了差分建图。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define N 100003
#define inf 2000000000
#define LL long long
using namespace std;
const LL INF=1e17;
int tot,nxt[N],point[N],v[N],remain[N],can[N],last[N],n,k,t1,t2,a[N],b[N];
LL cost[N],dis[N],ans;
void add(int x,int y,int z,LL k)
{
    tot++; nxt[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=z; cost[tot]=k;
    tot++; nxt[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; cost[tot]=-k;
}
int addflow(int s,int t)
{
    int ans=inf; int now=t;
    while (now!=s) {
        ans=min(ans,remain[last[now]]);
        now=v[last[now]^1];
    }
    now=t;
    while (now!=s) {
        remain[last[now]]-=ans;
        remain[last[now]^1]+=ans;
        now=v[last[now]^1];
    }
    return ans;
}
bool spfa(int s,int t)
{
    for (int i=1;i<=t;i++) dis[i]=INF,can[i]=0;;
    dis[s]=0; can[s]=1;
    queue<int> p; p.push(s);
    while (!p.empty()) {
        int now=p.front(); p.pop();
        can[now]=0;
        for (int i=point[now];i!=-1;i=nxt[i])
         if (remain[i]&&dis[v[i]]>dis[now]+cost[i]){
            dis[v[i]]=dis[now]+cost[i];
            last[v[i]]=i;
            if (!can[v[i]]) {
                can[v[i]]=1;
                p.push(v[i]);
             }
         }
    }
    if (dis[t]==INF) return false;
    int flow=addflow(s,t);
    ans+=dis[t];
    return true;
}
int main()
{
    freopen("delight.in","r",stdin);
    freopen("delight.out","w",stdout);
    scanf("%d%d%d%d",&n,&k,&t1,&t2);
    LL sum=0;
    tot=-1;
    memset(point,-1,sizeof(point));
    for (int i=1;i<=n;i++) scanf("%d",&a[i]),sum+=(LL)a[i];
    for (int i=1;i<=n;i++) scanf("%d",&b[i]);
    int mn=t2; int mx=k-t1;
    int S=n+1;  int SS=S+1; int TT=SS+1;
    for (int i=1;i<=n;i++) add(i,i+k>n?TT:i+k,1,-(b[i]-a[i]));
    for (int i=1;i<=n;i++) add(i,i+1>n?TT:i+1,mx-mn,0);
    for (int i=1;i<=k;i++) add(S,i,inf,0);
    add(SS,S,mx,0);
    while (spfa(SS,TT));
    printf("%lld\n",sum-ans);
    for (int i=1;i<=2*n-1;i+=2)
     if (remain[i]) printf("E");
     else printf("S");
    printf("\n");
}
View Code

E:贪心+排序+二分计算贡献

考虑到每一个i时刻要用的单车如果有等待时间那到i+1的这段时间都有贡献,故画出取车还车的折线图,在y=b这条线下的面积就是所求。

可以把每一个时间段取出来排序并求前缀和,然后二分来回答每一个询问。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 
 6 #define maxn 100000+5
 7 #define maxq 100000+5
 8 
 9 using namespace std;
10 
11 struct Query{
12     int pos,t;
13 }c[maxq];
14 
15 struct Event{
16     int opt,t,k;
17 }a[maxn];
18 
19 struct Data{
20     int len,val;
21     bool operator <(const Data &T)const{
22         return val<T.val;
23     }
24 }b[maxn];
25 
26 long long s[maxn],ss[maxn];
27 int n,q;
28 
29 bool cmp1(const Query & a,const Query &b){
30     return a.pos<b.pos;
31 }
32 
33 bool cmp2(const Query & a,const Query &b){
34     return a.t<b.t;
35 }
36 
37 int main(){
38     freopen("expect.in","r",stdin);
39     freopen("expect.out","w",stdout);
40     scanf("%d%d",&n,&q); 
41     for(int i=1;i<=n;i++){
42         char op; getchar();
43         scanf("%c%d%d",&op,&a[i].t,&a[i].k);
44         if(op=='-') a[i].opt=1;
45         else a[i].opt=2;
46     }
47     a[n+1].t=0x3f3f3f3f;
48     int now=0;
49     for(int i=1;i<=n;i++){
50         if(a[i].opt==1) now-=a[i].k;
51         else now+=a[i].k;
52         b[i].len=a[i+1].t-a[i].t;
53         b[i].val=now;
54     }
55     sort(b+1,b+1+n);
56     for(int i=1;i<=n;i++){
57         s[i]=s[i-1]+b[i].len;
58         ss[i]=ss[i-1]+(long long)b[i].len*b[i].val;
59     }
60     for(int i=1;i<=q;i++){
61         scanf("%d",&c[i].t);
62         if(c[i].t+now<0){
63             puts("INFINITY");
64             continue;
65         }
66         int l=1,r=n-1,ans=0;
67         while(l<=r){
68             int mid=(l+r)>>1;
69             if(-b[mid].val>c[i].t) ans=mid,l=mid+1;
70             else r=mid-1;
71         }
72         printf("%lld\n",-ss[ans]-s[ans]*c[i].t);
73     }
74     return 0;
75 }
View Code

F:概率DP

设dp[i]表示从i这里切一次,i以及i之后w的期望,很容易看出这是可以DP转移的

若i处是w,dp[i]=1/n*∑(∑(sum_c[i..j])+dp[j])否则是:dp[i]=1/n*∑(∑(sum_w[i..j])+dp[j]),维护一下sum_c和sum_w即可

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
using namespace std;
double sum[1000010],dp[1000010];
char str[1000010];
int n;

int main()
{
    freopen("foreign.in","r",stdin);
    freopen("foreign.out","w",stdout);
    int i;
    scanf("%s",str);
    n=strlen(str);
    for(i=0;i<n;i++)
    {
        if(str[i]=='C') sum[i]=1.0;
    }
    for(i=n-1;i>=0;i--) sum[i]+=sum[i+1];
    double sum_c=0.0,sum_w=0.0,cnt=0.0;
    if(str[n-1]=='C')sum_c=1.0;
    else sum_w=1.0;
    for(i=n-2;i>=0;i--)
    {

        if(str[i]=='C')
        {
            dp[i]=(cnt+sum_w)/(double)(n-i);
            sum_c+=(double)(n-i);
        }
        else
        {
            dp[i]=(cnt+sum_c)/(double)(n-i);
            sum_w+=(double)(n-i);
        }
        //cout<<dp[i]<<endl;
        cnt+=dp[i];
    }
    printf("%.10lf\n",dp[0]);
    //cout<<dp[0]<<endl;
    return 0;
}
View Code

J:物理题

用求重心的公式强行算即可,n^2的复杂度根本不虚

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <map>
const double eps=1e-10;
using namespace std;

struct zx
{
    double x,y;
};

zx zx_all[5010],zx_a[5010];
int n,w,h,m;
int vis[5010][5010];
int num[5010];
double le[5010],ri[5010];

int main()
{
    freopen("jenga.in","ri",stdin);
    freopen("jenga.out","w",stdout);
    int i,j;
    scanf("%d%d%d%d",&n,&w,&h,&m);
    int l,k;
    num[h+1]=0;
    for(i=h;i>=1;i--)
    {
        le[i]=0;
        ri[i]=n*w;
        num[i]=num[i+1]+n;
        zx_all[i].x=zx_a[i].x=(double)(n*w)/2.0;
        zx_all[i].y=zx_a[i].y=(double)(n*w)/2.0;
    }
    int ans=-1;
    for(i=1;i<=m;i++)
    {
        scanf("%d%d",&l,&k);
        if(ans!=-1) continue;
        vis[l][k]=1;
        for(j=l;j>=1;j--)
        {
            num[j]--;
            if(num[j]==num[j+1]||num[h]==0)
            {
                ans=i;
                break;
            }
        }
        if(ans!=-1) continue;
        if(num[l]==num[l+1])
        {
            ans=i;
            break;
        }
        else
        {
            for(j=1;j<=n;j++)
            {
                if(!vis[l][j])
                {
                    le[l]=(double)(j-1)*w;
                    break;
                }
            }
            for(j=n;j>=1;j--)
            {
                if(!vis[l][j])
                {
                    ri[l]=(double)j*w;
                    break;
                }
            }
        }
        double temp=0;
        double tmp=0;
        for(j=1;j<=n;j++)
        {
            if(!vis[l][j])
            {
                temp+=((j-1)*w+w/2);
                tmp+=1.0;
            }
        }
        temp/=tmp;
        if(l%2==1)
        {
            zx_a[l].x=temp;
        }
        else
        {
            zx_a[l].y=temp;
        }
        for(j=l;j>=1;j--)
        {
            zx_all[j].x=(zx_all[j+1].x*num[j+1]+zx_a[j].x*(num[j]-num[j+1]))/num[j];
            zx_all[j].y=(zx_all[j+1].y*num[j+1]+zx_a[j].y*(num[j]-num[j+1]))/num[j];
            if(j!=h&&(j&1)&&((zx_all[j+1].x<=le[j]||zx_all[j+1].x>=ri[j])||(fabs(zx_all[j+1].x-le[j])<eps)||(fabs(zx_all[j+1].x-ri[j])<eps)))
            {
                ans=i;
                break;
            }
            else if(j!=h&&!(j&1)&&((zx_all[j+1].y<=le[j]||zx_all[j+1].y>=ri[j])||(fabs(zx_all[j+1].y-le[j])<eps)||(fabs(zx_all[j+1].y-ri[j])<eps)))
            {
                ans=i;
                break;
            }
        }
    }
    if(ans==-1)
    {
        puts("no");
    }
    else
    {
        puts("yes");
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2018-07-13 23:16  Hetui  阅读(405)  评论(0编辑  收藏  举报