多校联考5

Rank:111   分数 160 再接再励
T1:思维+多情况考虑

T1:
一段数列,要求相邻数的差值<=1,给你特定的几个位置的值,求数列可能的最大值
如果是max出现在已经给出的数中,直接记录
如果出现在两个数之间,把两个数移动到值一样的地方,分奇数偶数区间讨论,求中间最大值就行
***如果出现在h[1],h[n]位置,题目没有限制的话,就可以单独成为最值

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<bitset>
#include<map>
#include<vector>
#include<deque>
#include<queue>
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define INF 2147483647
#define chu printf
#define ll long long
#define ull unsigned long long
using namespace std;
inline int re()
{
    int x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x;
}
const int N=1,MOD=1;
int n,m;
int id[200000+10],h[200000+10];
int mx;
int main()
{
    n=re(),m=re();
    _f(i,1,m)
    {
        id[i]=re(),h[i]=re();mx=max(mx,h[i]);
    }
    _f(i,1,m-1)
    {
        if(abs(h[i]-h[i+1])>id[i+1]-id[i])
        {
            chu("IMPOSSIBLE");return 0;
        }
    }
    _f(i,1,m-1)
    {
        if(h[i]<h[i+1])
        {
            int my=h[i]+(id[i+1]-id[i]+h[i+1]-h[i]-1)/2+((id[i+1]-id[i]+h[i+1]-h[i]-1)&1);
            mx=max(mx,my);
        }
        else 
        {
            int my=h[i+1]+(id[i+1]-id[i]+h[i]-h[i+1]-1)/2+((id[i+1]-id[i]+h[i]-h[i+1]-1)&1);
            mx=max(mx,my);
        }
        
    }//le8
    if(m==0)
    {
        chu("%d",100000000);return 0;
    }
    mx=max(mx,h[1]+id[1]-1);
    if(id[m]!=n)
    mx=max(mx,h[m]+n-id[m]);
    chu("%d",mx);
    return 0;
}
/*
8 2
2 0
7 0

8 3
2 0
7 0
8 3


*/
View Code

 T2:

给你一个数列a,求最长连续子序列满足任意两个元素val[i]-val[j]<=K

给出n,K,a[1--n]

考虑从1--n以此加入元素,对每个R,维护从1--R~R区间的最值(单调栈)

每次从队伍头判断当前ed--R的区间(目前最长区间)最大值和最小值出现的值是否满足<=K,如果满足更新ans,否则把区间左边界移动直到满足<=K的位置

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<bitset>
#include<map>
#include<vector>
#include<deque>
#include<queue>
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define INF 2147483647
#define chu printf
#define ll long long
#define ull unsigned long long
using namespace std;
inline int re()
{
    int x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x;
}
const int N=3000000+10,MOD=1;
int st1[N<<1],st2[N<<1],tp1,tp2,h1,h2;
int a[N],K,n;
int main()
{
    K=re(),n=re();
    _f(i,1,n)a[i]=re();
    int nas=0;h1=h2=1;
    int ed=1;
    _f(i,1,n)
    {
       // chu("cao %d %d\n",a[st1[tp1]],a[i]);
        while(tp1>=h1&&a[st1[tp1]]<a[i])
        --tp1;
        while(tp2>=h2&&a[st2[tp2]]>a[i])
        --tp2;
        st1[++tp1]=i;
        st2[++tp2]=i;
      //    chu("show max\n");
     //  _f(j,h1,tp1)chu("%d ",a[st1[j]]);
     //    chu("\n show min\n");
     //   _f(j,h2,tp2)chu("%d ",a[st2[j]]);
     //    chu("\n");
        while(h1<=tp1&&h2<=tp2&&a[st1[h1]]-a[st2[h2]]>K)
        {
           // chu("in\n");
            if(st1[h1]<st2[h2])
            {
                ++h1;
                ed=st1[h1-1]+1;
            }
            else ++h2,ed=st2[h2-1]+1;
        }
       // chu("%d %d\n",ed,i);
        nas=max(nas,i-ed+1);
    }
    chu("%d",nas);
    return 0;
}
/*
3 6
3 6 2 8 9 4
2 6
1 15 15 15 15 1

2 8
9 5 3 4 2 1 9 6

5000 50
2597 1573 5858 489 2080 
2718 3143 2616 1708 1288 
1762 2646 941 238 2145 4201
 5862 2880 284 3877 5084 2193 
 2576 2441 2750 434 4987 2487 
 4571 3626 1741 3546 5198 1599 
 4034 3657 4316 3555 2651 2402 
 4842 4412 1426 5782 4649 3570 
 362 891 2829 646
*/
View Code

 T3:

给你一段字符和Q个询问L,R求(L,R)区间的回文串数量

和分块没有关系,f[i][j]表示i,j区间的回文数量

g[][]表示是不是回文串

递推:f[i][j]=f[i+1][j]+f[i][j-1]-f[i+1][j-1]+g[i][j]

g[][]可以用中心拓展求

 

   g[1][1]=g[len][len]=1;
    _f(i,2,len-1)
    {
        int le=1;
        while((i-le)>=1&&(i+le)<=len&&s[i-le]==s[i+le])++le;
        _f(j,1,le)
        g[i-j+1][i+j-1]=1;
    }
    _f(i,1,len-1)//i--i+1是对称轴
    {
        if(s[i]!=s[i+1])continue;
        int le=1;
        while((i-le)>=1&&(i+1+le)<=len&&s[i-le]==s[i+1+le])++le;
        _f(j,1,le)
        g[i+1-j][i+j]=1;
    }

 

也可以用递推求,枚举起点终点,起点要倒着来,因为必须保证g[i+1][j-1]提前更新过

 

 

    for(int i=len;i>=1;--i)
    {
        g[i][i]=1;
        for(int j=i+1;j<=len;++j)
        {
            if(s[i]==s[j])g[i][j]=g[i+1][j-1];
            if(s[i]==s[j]&&i+1==j)g[i][j]=1;
        }
    }

 

DP:

    _f(i,1,len)//枚举区间长度
    {
        _f(j,1,len-i+1)
        {
            int st=j,ed=j+i-1;
            f[st][ed]=f[st+1][ed]+f[st][ed-1]-f[st+1][ed-1]+g[st][ed];
        }
    }


T4:给你一段字符串,可以对字符串进行前缀翻转,但是要求必须先翻转小的区间再翻转大的区间
并且要求指定长度的前缀不能翻转,求最小字典序串
正解

我打了暴力,60分

就是你找到3-4用的结论,然后进行操作暴力判断就行

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<iomanip>
#include<algorithm>
#include<bitset>
#include<map>
#include<vector>
#include<deque>
#include<queue>
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define INF 2147483647
#define chu printf
#define ll long long
#define ull unsigned long long
using namespace std;
inline int re()
{
    int x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x;
}
const int N=3000000+10;
ll MOD=998244353;
int s[300000+10];
bool nrt[300000+10];
int n,m;
inline void deal()
{
    _f(i,1,n)nrt[i]=0;
    n=re(),m=re();
    _f(i,1,n)s[i]=re();
    _f(i,1,m)
    {
        int hac=re();nrt[hac]=1;
    }
    int tiao=0;
    _f(i,2,n)//枚举翻哪位
    {
        if(nrt[i])
        {
            tiao++;
            continue;
        }
        //1--i-tiao-1
        int fan=i,zhen=1;
        int op=1;
        bool zhenxiao=1;
        int nct=0;
        while(nct<=i)
        {
            if(s[fan]>s[zhen])
            {zhenxiao=1;break;}
            if(s[zhen]>s[fan]){zhenxiao=0;break;}
            ++nct;
            ++zhen;
            if(op)--fan;
            else ++fan;
            if(fan==i-tiao-1)op=0,fan=1;
        }
        if(!zhenxiao)
        {
            reverse(s+1,s+1+i-tiao-1);
            reverse(s+1,s+1+i);
        }
        tiao=0;
     //    chu("\n");
    // _f(j,1,n)chu("()%d",s[j]);
    // chu("\n");
    }
   // chu("\n");
   // _f(i,1,n)chu("()%d",s[i]);
   // chu("\n");

   ll hsh=0;
   f_(i,n,1)
   hsh=(hsh*37+1LL*s[i])%MOD;
   chu("%lld\n",hsh);
    return ;

}
int main()
{
  //freopen("reverse1.in","r",stdin);
 // freopen("a.txt","w",stdout);
    int op=re();
    while(op--)
    {
        deal();
    }
    return 0;
}
/*
5
4 0
2 2 1 2
5 0
1 1 1 1 1
3 0
3 2 1
3 1
3 2 1
3
3 2
3 2 1
3 2
1
13 2
99 98 59 97 42 14 35 17 9 10 63 41 35
3 10
*/
60% TLE

 

posted on 2022-07-26 10:22  HZOI-曹蓉  阅读(25)  评论(0编辑  收藏  举报