2019牛客暑假多校训练营(第三场)

B:求一串01序列的最长子串,要求0、1个数相等。

把1看做-1,求一遍前缀和,如果s[r]-s[l-1]==0,满足条件,记录最开始的是s[l]在的位置。

#include
using namespace std;
 
const int N =1000*100+10;
char s[N];
int f[N];
int n;
mapmp;
 
int main(){
    scanf("%d",&n);
    scanf("%s",s+1);
    for(int i=1;i<=n;i++){
        if(s[i]=='1')f[i]=1;
        else f[i]=-1;
        f[i]+=f[i-1];
    }
    int len=0;
     
    for(int i=1;i<=n;i++){
        if(f[i]==0)len=max(len,i);//f[i]==0出现的位置在最开始
        if(mp[f[i]])len=max(len,i-mp[f[i]]);
        else mp[f[i]]=i;
    }
     
    printf("%d\n",len);
    return 0;
}

H:给出偶数个点,求一条直线,分成两部分,具有相等的点数,用直线上两个点表示直线。

比赛的时候wa哭了,一个错在y轴是从小到上变化,一个错在求平分两点的直线没有加y轴。

按照x轴坐标从小到大,y轴坐标从小到大排,按照象限变化,所以直线要往左偏。

#include
using namespace std;
struct p{int x,y;}t[1010];
 
int main(){
    int T; cin>>T;   
    while(T--){
        int n; cin>>n;
        for(int i=1;i<=n;i++)cin>>t[i].x>>t[i].y;
        sort(t+1,t+1+n,[](p a,p b){return a.x==b.x?a.y

F:给出n*n的方格,不断的取出矩形,最大值减去最小值小于等于m,问能取的矩形最大面积。

枚举上下边界,计算出每列的最大最小值,不断向右扩展的同时判断合法左边界。

用两个单调队列来维护,最小值的单调队列下标增大,所在的列最小值增加。

最大值的单调队列下标增大,所在列最大值减小。

最小值的单调队列下标增大,所在列最小值增大。

注意刚开始,头为1,尾为0

增大右边界时,为维护单调性,取出队尾不满足条件的,不考虑即可

头部两个最小值队列 最大,最大值队列 最小,判断两者大小是否满足题意。

#include
using namespace std;
const int inf=1e5+5;
int a[505][505],b[505],c[505];
int t,n,m;
int q1[505],q2[505];
int main()
{
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        memset(a,0,sizeof(a));
        int ans=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                b[j]=inf;
                c[j]=-inf;
            }
            for(int j=i;j<=n;j++){
                int h1=1,t1=0,h2=1,t2=0,l=1;
                for(int k=1;k<=n;k++){
                    b[k]=min(b[k],a[j][k]);
                    c[k]=max(c[k],a[j][k]);
                    while(h1<=t1&&b[k]c[q2[t2]]) t2--;
                    q2[++t2]=k;
                    while(l<=k&&(c[q2[h2]]-b[q1[h1]])>m){
                        l++;
                        if(q1[h1]

J:模拟 map

0号操作:若查询的字符串已加入到数组中,就把它取出来,原有值保持不变,压入数组末尾。否则直接加入到末尾,值为输入的v。

1号操作:先得出输入的字符串在数组中的下标k,查询下标为(k+v)的数组元素的值,若k或(k+v)不存在都输出Invalid。

unordered_map比map快四五百毫秒。

#include
using namespace std;
int q,m,op,v,k;
char s[20];
struct node
{
    string s;
    int data;
};
list lst;
list::iterator it;
unordered_map::iterator> mp;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&q,&m);
        mp.clear();
        lst.clear();
        for(int i=0;is);
                        lst.erase(lst.begin());
                    }
                    lst.push_back(node{s,v});
                    it=lst.end();it--;
                    mp[s]=it;
                    printf("%d\n",v);
                }
                else{
                    it=mp[s];
                    printf("%d\n",it->data);
                    lst.erase(it);
                    lst.push_back(node{s,it->data});
                    it=lst.end();it--;
                    mp[s]=it;
                }
            }
            else{
                 if(mp.count(s)==0) printf("Invalid\n");
                 else{
                    it=mp[s];
                     if(v==0){
                        printf("%d\n",it->data);
                     }
                     else if(v==-1){
                        if(it==lst.begin()) printf("Invalid\n");
                        else{
                            it--;
                            printf("%d\n",it->data);
                        }
                     }
                     else{
                        it++;
                        if(it==lst.end()) printf("Invalid\n");
                        else{
                            printf("%d\n",it->data);
                        }
                     }
                 }
            }
        }
    }
    return 0;
}

 

你可能感兴趣的:(牛客网比赛)