zoukankan      html  css  js  c++  java
  • 2019牛客多校第三场

    B.Crazy Binary String

    传送:https://ac.nowcoder.com/acm/contest/883/B

    题意:有一个长度为$n$的‘0’’1‘字符串,询问’0‘,’1‘个数相同的最长的子串和子序列为多长。

    数据范围:$1<=n<=10^5$。

    分析:首先考虑子序列,那么就是$ans2=min(num[0],num[1])*2$。

    将0变为-1,做前缀和。找前缀和相等的跨越长度最大的即可。同时需要特别0位置设为0。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1e5+10;
     4 int num[maxn];
     5 map<int,int> mp;
     6 vector<int> g[2*maxn];
     7 int main(){
     8     string s; 
     9     int n;scanf("%d",&n);
    10     cin >> s;
    11     int kk=0;
    12     for (int i=0;i<n;i++){
    13         if (s[i]=='0'){
    14             num[i+1]=-1;
    15             kk++;
    16         }
    17         else num[i+1]=1;
    18     }
    19     kk=min(kk,n-kk);
    20     int ans2=kk*2;
    21     num[0]=0;
    22     for (int i=2;i<=n;i++) num[i]=num[i]+num[i-1];
    23     int tot=0;
    24     for (int i=0;i<=n;i++){
    25         if (mp[num[i]]==0){
    26             mp[num[i]]=++tot;
    27             g[tot].push_back(i);
    28         }
    29         else g[mp[num[i]]].push_back(i);
    30     } 
    31     int ans1=0;
    32     for (int i=1;i<=tot;i++){
    33         if (g[i].size()>=2){
    34             int tmp=g[i][g[i].size()-1]-g[i][0];
    35             ans1=max(ans1,tmp);
    36         }
    37     }
    38     printf("%d %d
    ",ans1,ans2);
    39     return 0;
    40 } 
    B

    F.Planting Trees

    传送:https://ac.nowcoder.com/acm/contest/883/F

    题意:有一个$n*n$大小的矩阵,求解一个最大的子矩阵,要求这个子矩阵内任意两个数的差的绝对值$<=m$。

    数据范围:$1<=n<=500,a_{ij}<=10^5$。

    分析:读完题觉得需要维护子矩阵的最大最小值。写了二维线段树,然后枚举起始行和终止行,再尺取法找列。(然而,线段树复杂度太大,tle。

    正解是:枚举起始行和终止行,再枚举右边界去找到可行的最小的左边界。

    在枚举右边界的同时,维护两个单调队列,维护最大值和最小值,

    最小值的单调队列应该为:下标递增,大小递增;最大值的单调队列应该为:下标递增,大小递解。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int INF=2333333;
     4 const int maxn=510;
     5 int a[maxn][maxn],mi[maxn],mx[maxn],q1[maxn],q2[maxn];
     6 int main(){
     7     int t,n,m;scanf("%d",&t);
     8     while (t--){
     9         scanf("%d%d",&n,&m);
    10         for (int i=1;i<=n;i++)
    11             for (int j=1;j<=n;j++) scanf("%d",&a[i][j]);
    12         int ans=0;
    13         for (int i=1;i<=n;i++){
    14             for (int j=1;j<=n;j++) mi[j]=INF,mx[j]=-INF;
    15             for (int j=i;j<=n;j++){
    16                 for (int k=1;k<=n;k++){
    17                     mi[k]=min(mi[k],a[j][k]);
    18                     mx[k]=max(mx[k],a[j][k]);
    19                 }
    20                 int l1=1,r1=0,l2=1,r2=0;
    21                 for (int l=1,r=1;r<=n;r++){
    22                     while (l1<=r1 && mx[r]>=mx[q1[r1]]) r1--;
    23                     q1[++r1]=r;
    24                     while (l2<=r2 && mi[r]<=mi[q2[r2]]) r2--;
    25                     q2[++r2]=r;
    26                     while (l<=r && mx[q1[l1]]-mi[q2[l2]]>m){
    27                         while (l1<=r1 && q1[l1]<=l) l1++;
    28                         while (l2<=r2 && q2[l2]<=l) l2++;
    29                         l++;
    30                     }
    31                     ans=max(ans,(j-i+1)*(r-l+1));
    32                 }
    33             } 
    34         }
    35         printf("%d
    ",ans);
    36     }
    37     return 0;
    38 }
    F

    另,对面顾老师二维ST表也过了,%%%%%,tttttttql。顾老师代码:

     1 #include<bits/stdc++.h>
     2 #define rep(i,x,y) for(int i=(x);i<=(y);++i)
     3 #define dep(i,x,y) for(int i=(x);i>=(y);--i)
     4 #define pb push_back
     5 #define fr first
     6 #define sc second
     7 using namespace std;
     8 typedef long long ll;
     9 const int N=510;
    10 int mx[9][9][N][N],mi[9][9][N][N],a[N][N],rd[N*2];
    11 struct fastio{
    12     static const int s=1<<24;
    13     int p,l;
    14     fastio(){p=l=0;}
    15     inline char gc(){
    16         static char bf[s];
    17         if(p==l)p=0,l=fread(bf,1,s,stdin);
    18         return p==l?-1:bf[p++];
    19     }
    20     inline bool read(int&x){
    21         char c=gc();
    22         while((c<'0'||c>'9')&&~c)c=gc();
    23         if(c==-1)return 0;x=0;
    24         for(;c>='0'&&c<='9';c=gc())x=x*10+c-'0';
    25         return 1;
    26     }
    27 }io;
    28 int cal(int lx,int ly,int rx,int ry){
    29     int tx=rd[rx-lx+1],ty=rd[ry-ly+1];
    30     int zx=rx-(1<<tx)+1;
    31     if(ly==ry)return max(mx[tx][0][lx][ly],mx[tx][0][zx][ly])-
    32     min(mi[tx][0][lx][ly],mi[tx][0][zx][ly]);
    33     int zy=ry-(1<<ty)+1;
    34     return max(max(mx[tx][ty][lx][ly],mx[tx][ty][zx][ly]),
    35     max(mx[tx][ty][lx][zy],mx[tx][ty][zx][zy]))-
    36     min(min(mi[tx][ty][lx][ly],mi[tx][ty][zx][ly]),
    37     min(mi[tx][ty][lx][zy],mi[tx][ty][zx][zy]));
    38 }
    39 int tot;
    40 void sol(){
    41     int n,m,ans=0;
    42     io.read(n);io.read(m);int t=rd[n];
    43     rep(i,1,n)rep(j,1,n)io.read(a[i][j]);
    44     rep(i,1,n)rep(j,1,n)mi[0][0][i][j]=mx[0][0][i][j]=a[i][j];
    45     rep(i,0,t-1)rep(j,1,n)rep(k,1,n){int r=j+(1<<i);
    46         if(r>n){
    47             mi[i+1][0][j][k]=mi[i][0][j][k];
    48             mx[i+1][0][j][k]=mx[i][0][j][k];
    49         }else{
    50             mi[i+1][0][j][k]=min(mi[i][0][j][k],mi[i][0][r][k]);
    51             mx[i+1][0][j][k]=max(mx[i][0][j][k],mx[i][0][r][k]);
    52         }
    53     }
    54     rep(i,0,t)rep(j,0,t-1)rep(k,1,n)rep(l,1,n){int r=l+(1<<j);
    55         if(r>n){
    56             mi[i][j+1][k][l]=mi[i][j][k][l];
    57             mx[i][j+1][k][l]=mx[i][j][k][l];
    58         }else{
    59             mi[i][j+1][k][l]=min(mi[i][j][k][l],mi[i][j][k][r]);
    60             mx[i][j+1][k][l]=max(mx[i][j][k][l],mx[i][j][k][r]);
    61         }
    62     }
    63     rep(i,1,n)rep(j,1,n){
    64         int x=j,mi1=a[i][j],mx1=a[i][j];
    65         while(x<=n&&mx1-mi1<=m){
    66             ++x;mi1=min(mi1,a[i][x]);mx1=max(mx1,a[i][x]);
    67         }
    68         ans=max(ans,x-j);--x;
    69         rep(k,i+1,n){
    70             while(x>=j&&cal(i,j,k,x)>m)--x;
    71             if((n-i+1)*(x-j+1)<=ans)break;ans=max(ans,(k-i+1)*(x-j+1));
    72         }
    73     }printf("%d
    ",ans);
    74 }
    75 int main(){
    76     rep(i,0,8)rep(j,(1<<i)+1,2<<i)rd[j]=i;
    77     int t;io.read(t);
    78     rep(i,1,t)sol();
    79 }
    F2

    H.Magic Line

    传送:https://ac.nowcoder.com/acm/contest/883/H

    题意:给定平面上的$n$个点,确定一条直线将其划分为数量相等的两部分。

    数据范围:$1<=T<=10^5,1<=n<=1000,|x_i,y_i|<=1000$。

    分析:移动坐标轴,将所有点放在第一象限,然后根据与x轴的斜率排序,斜率相同根据距离排序。

    答案直线一定经过中间两点的中间。

    然后在第三象限取一个较远的点,然后另一个点就是中间两点的中位点。(再保证答案为整数即可。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=1005;
     4 typedef long long ll;
     5 struct node{ll x,y,s;} p[maxn];
     6 bool cmp(node a,node b)
     7 {
     8     ll xx=a.x*b.y-b.x*a.y;
     9     return (xx>0 || ((xx==0)&&a.s<b.s));
    10 }
    11 int main()
    12 {
    13     int t;scanf("%d",&t);
    14     while (t--)
    15     {
    16         int n;scanf("%d",&n);
    17         for (int i=0;i<n;i++)
    18         {
    19             ll xx,yy;
    20             scanf("%lld%lld",&xx,&yy);
    21             p[i].x=1ll*3000+xx;
    22             p[i].y=1ll*50000+yy;
    23             p[i].s=xx*xx+yy*yy;
    24         }
    25         sort(p,p+n,cmp);
    26         node A=p[n/2-1],B=p[n/2];
    27         A.x=A.x*2-3000;B.x=B.x*2-3000;
    28         A.y=A.y*2-50000;B.y=B.y*2-50000;
    29         printf("-3000 -50000 %lld %lld
    ",(A.x+B.x)/2,(A.y+B.y)/2);
    30     }
    31     return 0;
    32 }
    H

     J.LRU management

    传送:https://ac.nowcoder.com/acm/contest/883/J

    题意:定义LRU算法如下:

    操作0:将名字为$s$,数据为$v$的元素放入列表内。如果存在列表内就将原来的取出添加至最后一个位置,否则直接添加到最后。输出$v$。

    操作1:查找名字为$s$的元素的位置$k$,并输出$k+xx$位置的数据$v$。

    同时列表只能容纳$m$个元素,如果超出,则弹出最早的元素。

     数据范围:$1<=q,m<=5e5$

    分析:list+map模拟。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 struct node{
     4     string s,v;
     5     node(){}
     6     node(string _s,string _v){
     7         s=_s; v=_v; 
     8     }
     9 };
    10 int m,q;
    11 list<node> lt;
    12 unordered_map<string,list<node>::iterator> mp;
    13 void solve(string s){
    14     char v[20];scanf("%s",v);
    15     if (mp.find(s)!=mp.end()){
    16         auto it=mp[s];
    17         strcpy(v,it->v.data());
    18         lt.erase(it);
    19     }
    20     node tmp; tmp.s=s; tmp.v=v;
    21     lt.emplace_back(tmp);
    22     mp[s]=prev(lt.end());
    23     printf("%s
    ",v);
    24     if (lt.size()>m){
    25         mp.erase(lt.begin()->s);
    26         lt.pop_front();
    27     }
    28 }
    29 void solve2(string s){
    30     int v;scanf("%d",&v);
    31     if (mp.find(s)==mp.end()){
    32         printf("Invalid
    ");
    33         return ;
    34     }
    35     auto it=mp[s];
    36     if (it==lt.begin() && v==-1 || next(it)==lt.end() && v==1){
    37         printf("Invalid
    ");
    38         return ;
    39     }
    40     if (v==1) it=next(it);
    41     else if (v==-1) it=prev(it);
    42     printf("%s
    ",it->v.data());
    43 }
    44 int main(){
    45     int t,op;scanf("%d",&t);
    46     char s[30];
    47     while (t--){
    48         lt.clear();mp.clear();
    49         scanf("%d%d",&q,&m);
    50         while (q--){
    51             scanf("%d",&op);
    52             scanf("%s",&s);
    53             if (op==0) solve(s);
    54             else solve2(s);
    55         }
    56     }
    57     return 0;
    58 } 
    J

    注:emplace_back优于push_back。用构造函数会比先赋值好再放入费时。

     

  • 相关阅读:
    L1-018 大笨钟 (10分)
    L1-017 到底有多二 (15分)
    L1-016 查验身份证 (15分)
    L1-015 跟奥巴马一起画方块 (15分)
    L1-014 简单题 (5分)
    L1-013 计算阶乘和 (10分)
    L1-012 计算指数 (5分)
    L1-011 A-B (20分)
    L1-010 比较大小 (10分)
    L1-009 N个数求和 (20分)
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/11247813.html
Copyright © 2011-2022 走看看