[游记]2022年多校冲刺NOIP联训测试5-2022.7.25

今日份智障错误:看错比赛时间+没有删 $\operatorname{freopen}$

然后就爆炸了,$190/400$

A. 旅行日记

显然的一个贪心,但是要注意一些奇奇怪怪的条件

不难发现,设当次的时间是 $t[i]$ ,高度是 $h[i]$

那么在这次和上次之间最高能到达的高度就是 $\max{(h[i],h[i-1])}+\dfrac{(t[i]-t[i-1]-\left\vert h[i]-h[i-1]\right\vert ))}{2}$

注意处理第一个和第 $n$ 个的情况否则会挂到 $80$ 分,比如他有可能在第一天到了一个比较高的高度然后一直在走下坡路

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=1001000,INF=1099511627776;
int n,m;
int t[WR],h[WR];
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
signed main(){
    n=read(),m=read();
    t[1]=read(),h[1]=read();
    int maxx=t[1]-1+h[1];
    for(int i=2;i<=m;i++){
        t[i]=read(),h[i]=read();
        maxx=max(h[i],maxx);
        if(abs(h[i]-h[i-1])>t[i]-t[i-1]){
            printf("IMPOSSIBLE");
            return 0;
        }
        maxx=max(maxx,max(h[i],h[i-1])+(t[i]-t[i-1]-abs(h[i]-h[i-1]))/2);
    }
    printf("%lld",maxx);
    return 0;
}
View Code

 

B. 运动

这,一开始我考虑了用线段树维护最大最小值,然后移动两个指针维护区间左右端点

具体一点就是类似莫队,先让右端点指针无限右移到差值大于 $k$ 然后让左端点右移 $1$ ,直到右端点到达 $n$ 为止

然鹅时间复杂度是 $\Theta(Cn\log n)$ ,$C$ 是一个理论上小于等于 $4$ 的常数

然鹅最大数据三百万不是特别可过,因此我向来会被卡,这次也被卡成了 $90$ 分

代码被一次突如其来的停电吃了,于是更新了一版单调栈做法,思路是一样的但复杂度变为 $\Theta(n)$

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=5001000,INF=2147483647;
int n,k;
int a[WR];
int que1[WR],hd1,sze1;
int que2[WR],hd2,sze2;
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
signed main(){
    k=read(),n=read();
    for(int i=1;i<=n;i++) a[i]=read();
    hd1=hd2=1;a[0]=a[1];
    int ans=1,pos=1;
    for(int i=1;i<=n;i++){
        while(que1[hd1]<i&&hd1<=sze1) ++hd1;
        while(que2[hd2]<i&&hd2<=sze2) ++hd2;
        while(pos<=n){
            int maxx=-INF,minn=INF;
            if(hd1<=sze1) maxx=a[que1[hd1]];
            maxx=max(maxx,a[pos]);
            if(hd2<=sze2) minn=a[que2[hd2]];
            minn=min(minn,a[pos]);
            if(maxx-minn>k) break;
            while(hd1<=sze1&&a[que1[sze1]]<a[pos]) sze1--;
            que1[++sze1]=pos;
            while(hd2<=sze2&&a[que2[sze2]]>a[pos]) sze2--;
            que2[++sze2]=pos;
            pos++;
        }
        ans=max(ans,pos-i);
    }
    printf("%lld\n",ans);
    return 0;
}
View Code

 

C. 回文

一开始以为是 $\operatorname{manacher}$ 后来发现算法瓶颈不在于这里

考虑 $\operatorname{DP}$ ,可以首先设 $dp[i][j]$ 为 $i\to j$ 是否是回文串进行一个预处理

预处理可以用 $\operatorname{hash}$ 做到 $\Theta(n^2)$

然后更改 $dp$ 数组的意义,令 $dp[i][j]$ 维护 $(1,1)$ 到 $(i,j)$ 区间内的回文个数,便可以做到 $\Theta(1)$ 查询

 

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<string>
#define int long long
#define WR WinterRain
using namespace std;
const int WR=1001000,INF=2147483647;
const int base=233;
char str[WR];
int len;
int dp[5020][5020];
struct Hash{
    unsigned int hash[WR],bse[WR];
    void init(){
        bse[0]=hash[0]=1;
        for(int i=1;i<=WR;i++){
            bse[i]=bse[i-1]*base;
        }
    }
    void get_hash(char str[]){
        for(int i=1;i<=strlen(str+1);i++){
            hash[i]=hash[i-1]*base+str[i]-'a';
        }
    }
    unsigned int query(int l,int r){
        return hash[r]-hash[l-1]*bse[r-l+1];
    }
}forw,bckw;
int read(){
    int s=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        s=(s<<3)+(s<<1)+ch-48;
        ch=getchar();
    }
    return s*w;
}
signed main(){
    scanf("%s",str+1);
    len=strlen(str+1);
    forw.init(),bckw.init();
    forw.get_hash(str);
    reverse(str+1,str+1+len);
    bckw.get_hash(str);
    for(int i=1;i<=len;i++){
        for(int j=i;j<=len;j++){
            if(forw.query(i,j)==bckw.query(len-j+1,len-i+1)) dp[i][j]=1;
            else dp[i][j]=0;
            //printf("%lld ",dp[i][j]);
        }
        //printf("\n");
    }
    for(int i=1;i<=len;i++){
        for(int j=1;j<=len;j++){
            dp[i][j]=dp[i][j]+dp[i][j-1]+dp[i-1][j]-dp[i-1][j-1];
        }
    }
    int q=read();
    while(q--){
        int l=read(),r=read();
        printf("%lld\n",dp[r][r]-dp[r][l-1]-dp[l-1][r]+dp[l-1][l-1]);
    }
    return 0;
}
View Code

 

D. 基因进化

 

posted @ 2022-07-26 20:46  冬天丶的雨  阅读(36)  评论(0编辑  收藏  举报
Live2D