• codeforces Round #541 (Div 2)


    A Sea Battle

    平移过后即外围的$(w_{2} + 2) imes  (h_{1} + h_{2} + 2)$的矩形周长;

    1 #include<bits/stdc++.h>
    2 using namespace std;
    3 int main(){
    4     int w1,w2,h1,h2;
    5     cin>>w1>>h1>>w2>>h2;
    6     int a=w1+2,b=h1+h2+2;
    7     cout<<((a+b)<<1)-4<<endl;
    8     return 0;
    9 }
    View Code

    B Draw!

     为了方便设初始比分为$(-1,-1)$,假设上一次的比分为$(x_{0},y_{0})$,这次比分为$(x_{1},y_{1})$

    若:1.$max(x_{0} , y_{0}) > min(x_{1} , y_{1}) $ 此时变化中一定不会出现相同的情况;

           2.$max(x_{0} , y_{0}) <= min(x_{1} , y_{1})$最优的情况是将$x_{0},y_{0}$都先变成较大值,再一起增加,最后再单个增加;

    注意对$x==y$的一点点特判;

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,a,b,la,lb;
     4 int main(){
     5     scanf("%d",&n);
     6     la=lb=-1;
     7     long long ans=0;
     8     for(int i=1;i<=n;++i){
     9         scanf("%d%d",&a,&b);
    10         ans+=max(min(a,b)-max(la,lb)+(la!=lb),0);
    11         la=a,lb=b;
    12     }
    13     cout<<ans<<endl;
    14     return 0;
    15 }
    View Code

    C Birthday

    做法好像还挺多,我不会证明,所以虽然过了也不知对不对,如果评论区有大佬路过的话欢迎评论;

    比较麻烦的是两端怎么处理;

    排序之后左半边奇数位顺序排列,然后再接偶数位的逆序排列;

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=110;
     4 int n,a[N];
     5 int main(){
     6     scanf("%d",&n);
     7     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
     8     sort(a+1,a+n+1);
     9     for(int i=1;i<=n;i+=2)printf("%d ",a[i]);
    10     if(n&1)n--;for(int i=n;i;i-=2)printf("%d ",a[i]);
    11     return 0;
    12 }
    View Code

    D Gourmet choice

    相当于只有'>','=',对等于符号用并查集缩点;

    对x>y建边:x->y;

    对于得到DAG,记录一个点出发的最长链,即为答案;

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=2010;
     4 int n,m,f[N],mx[N],o=1,hd[N],vis[N];
     5 char s[N][N];
     6 struct Edge{int v,nt;}E[N*N];
     7 void adde(int u,int v){E[o]=(Edge){v,hd[u]};hd[u]=o++;}
     8 bool dfs(int u){
     9     mx[u]=vis[u]=1;
    10     for(int i=hd[u];i;i=E[i].nt){
    11         int v=E[i].v;
    12         if(vis[v]==1)return false;
    13         if(!vis[v]){if(!dfs(v))return false;}
    14         mx[u]=max(mx[u],mx[v]+1);
    15     }
    16     vis[u]=2;
    17     return true;
    18 }
    19 int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    20 int main(){
    21     #ifndef ONLINE_JUDGE
    22     freopen("D.in","r",stdin);
    23     freopen("D.out","w",stdout);
    24     #endif
    25     scanf("%d%d",&n,&m);
    26     for(int i=1;i<=n+m;++i)f[i]=i;
    27     for(int i=1;i<=n;++i)scanf("%s",s[i]+1);
    28     for(int i=1;i<=n;++i)
    29     for(int j=1;j<=m;++j)if(s[i][j]=='=')f[find(i)]=find(j+n);
    30     for(int i=1;i<=n;++i)
    31     for(int j=1;j<=m;++j)
    32     if(s[i][j]=='>')adde(find(i),find(j+n));
    33     else if(s[i][j]=='<')adde(find(j+n),find(i));
    34     for(int i=1;i<=n+m;++i)if(find(i)==i&&!vis[i]){
    35         if(!dfs(i)){puts("NO");return 0;}
    36     }
    37     puts("YES");
    38     for(int i=1;i<=n;++i)printf("%d ",mx[find(i)]);
    39     printf("
    ");
    40     for(int i=1;i<=m;++i)printf("%d ",mx[find(i+n)]);
    41     printf("
    ");
    42     return 0;
    43 }
    View Code

    E String Multiplication

    考虑每一个字符,分情况模拟即可:
    对于$a+b$,

    如果$b$是一个全为$x$的串,仅会连接原来的字符$x$,其余置1;

    如果$b$是一个首末连续段不相接但是都为$x$的段,修改$x$,其余置1;

    如果$b$是一个首末连续段不相接为$x,y(x!=y)$的段,修改$x,y$,其余置1;

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=100010;
     4 int n,len,a[26],b[26],lt,p1,p2;
     5 char s[N];
     6 inline void upd(int&x,int y){if(x<y)x=y;}
     7 void cal(){
     8     len=strlen(s+1);
     9     p1=1;while(p1<len&&s[1]==s[p1+1])p1++;
    10     p2=1;while(p2<len&&s[len]==s[len-p2])p2++;
    11     for(int i=1,cnt=1;i<len;++i)if(s[i]!=s[i+1]){
    12         upd(a[s[i]-'a'], cnt);
    13         cnt=1;
    14     }else cnt++;
    15     upd(a[s[len]-'a'], p2);
    16 }
    17 int main(){
    18     #ifndef ONLINE_JUDGE
    19     freopen("E.in","r",stdin);
    20     freopen("E.out","w",stdout);
    21     #endif
    22     scanf("%d",&n);
    23     scanf("%s",s+1);cal();
    24     for(int i=0;i<26;++i)b[i]=a[i],a[i]=0;
    25     for(int i=1;i<n;++i){
    26         scanf("%s",s+1);cal();
    27         if(p1==len){
    28             int x=s[1]-'a';
    29             b[x]=a[x]*b[x]+a[x]+b[x];
    30             for(int j=0;j<26;++j)if(j!=x)b[j]=b[j]?1:0;
    31         }else if(s[1]==s[len]){
    32             int x=s[1]-'a';
    33             if(b[x])b[x]=p1+p2+1;
    34             for(int j=0;j<26;++j)if(j!=x)b[j]=b[j]?1:0;
    35         }else{
    36             int x=s[1]-'a',y=s[len]-'a';
    37             if(b[x])b[x]=p1+1;
    38             if(b[y])b[y]=p2+1;
    39             for(int j=0;j<26;++j)if(j!=x&&j!=y)b[j]=b[j]?1:0;
    40         }
    41         for(int j=0;j<26;++j)upd(b[j],a[j]),a[j]=0;
    42     }
    43     int ans=0;
    44     for(int i=0;i<26;++i)upd(ans, b[i]);
    45     cout<<ans<<endl;
    46     return 0;
    47 }
    View Code

    F Asya And Kittens

    用并查集模拟,同时维护两边的位置即可

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=150100;
     4 int n,d[N],pre[N],nxt[N],f[N];
     5 vector<int>g[N];
     6 void adde(int u,int v){
     7     g[u].push_back(v);
     8     g[v].push_back(u);
     9     d[u]++;
    10     d[v]++;
    11 }
    12 void dfs(int u,int fa){
    13     printf("%d ",u);
    14     for(int i=0;i<(int)g[u].size();++i){
    15         if(g[u][i]!=fa)dfs(g[u][i],u);
    16     }
    17 }
    18 int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
    19 int main(){
    20     scanf("%d",&n);
    21     for(int i=1;i<=n;++i)pre[i]=nxt[i]=f[i]=i;
    22     for(int i=1;i<n;++i){
    23         int x,y;
    24         scanf("%d%d",&x,&y);
    25         x=find(x),y=find(y);
    26         adde(nxt[x],pre[y]);
    27         nxt[x]=nxt[y];
    28         f[y]=x;
    29     }
    30     int rt=0;
    31     for(int i=1;i<=n;++i)if(d[i]==1){rt=i;break;}
    32     dfs(rt,0);
    33     return 0;
    34 }
    View Code

     G Most Dangerous Shark

    这题倒还不错;

    先考虑如果只有向左倒怎么办;

    一个骨牌向左可以压倒的一定是一段区间,

    由于连续效应,$n$张骨牌可以形成若干段区间,这些区间互不相交,只要贪心选右端点即可;

    处理所有向左的范围只需要依次加入,用一个栈维护所有右端点,每次加入弹出并合并末尾的若干当前点$i$可到的右端点;

    同理可以预处理向右的范围;

    回到原题,$dp[i]$表示前$i$个的答案;

    考虑转移$(j<i)$,一个是$i$向左推倒$j$转移,一个是$j$向右倒到$i$转移;

    第一种直接从$i$可推倒的最远$j$转移即可;

    第二种,当$j1<j2$并且$j1$可以推倒$j2$,同时$dp[j1-1]+c_{j1}<dp[j2-1]+c_{j2}$,$j2$显然不会更优:

    所以可以用一个栈维护$dp[i-1]+c_{i}$的降序即可;

     1 #include<bits/stdc++.h>
     2 #define ll long long 
     3 using namespace std;
     4 const int N=250010,M=10000010;
     5 int n,m,q,ta[M],tb[M],a[M],len[N],l[M],r[M],st[M],tp;
     6 ll b[M],dp[M]; 
     7 char gc(){
     8     static char*p1,*p2,s[1000000];
     9     if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
    10     return(p1==p2)?EOF:*p1++;
    11 }
    12 int rd(){
    13     int x=0;char c=gc();
    14     while(c<'0'||c>'9')c=gc();
    15     while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
    16     return x;
    17 }
    18 int main(){
    19     //freopen("G.in","r",stdin);
    20     //freopen("G.out","w",stdout);
    21     n=rd();m=rd();
    22     for(int i=1,now;i<=n;++i){
    23         len[i]=rd();
    24         now=len[i-1];for(int j=1;j<=len[i];++j)ta[++now]=rd();
    25         now=len[i-1];for(int j=1;j<=len[i];++j)tb[++now]=rd();
    26         len[i]+=len[i-1];
    27     }
    28     q=rd();
    29     for(int i=1,now=0;i<=q;++i){
    30         int id=rd(),mul=rd(),tmp=now;
    31         for(int j=len[id-1]+1;j<=len[id];++j)a[++tmp]=ta[j];
    32         for(int j=len[id-1]+1;j<=len[id];++j)b[++now]=1ll*tb[j]*mul;
    33     }
    34     for(int i=1;i<=m;++i){
    35         l[i]=max(1,i-a[i]+1);
    36         while(tp&&st[tp]>=l[i])l[i]=min(l[i],l[st[tp--]]);
    37         st[++tp]=i;
    38     }tp=0;
    39     for(int i=m;i>=1;--i){
    40         r[i]=min(m,i+a[i]-1);
    41         while(tp&&st[tp]<=r[i])r[i]=max(r[i],r[st[tp--]]);
    42         st[++tp]=i;
    43     }tp=0;
    44     for(int i=1;i<=m;++i){
    45         dp[i]=dp[l[i]-1]+b[i];
    46         while(tp&&r[st[tp]]<i)tp--;
    47         if(tp)dp[i]=min(dp[i],dp[st[tp]-1]+b[st[tp]]);
    48         if(!tp||dp[i-1]+b[i]<dp[st[tp]-1]+b[st[tp]])st[++tp]=i;
    49     }
    50     cout<<dp[m]<<endl;
    51     return 0;
    52 }
    View Code
  • 相关阅读:
    《O2O实战:他们是如何利用互联网的》.pdf
    建议收藏,mybatis插件原理详解
    《Tensorflow:实战Google深度学习框架》.pdf
    MyBatis插件原理及应用(上篇)
    《大数据算法》.pdf
    答了Mybatis这个问题后,面试官叫我回去等通知……
    《构建高性能WEB站点》.pdf
    SpringBoot 构建 Docker 镜像的最佳 3 种方式
    快速了解阿里微服务热门开源分布式事务框架——Seata
    超值干货 | 建议收藏:精美详尽的 HTTPS 原理图注意查收!
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10425270.html
Copyright © 2020-2023  润新知