ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

多校联考5

2022-07-26 10:33:41  阅读:116  来源: 互联网

标签:ch int 多校 long chu include 联考 define


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

 

标签:ch,int,多校,long,chu,include,联考,define
来源: https://www.cnblogs.com/403caorong/p/16518695.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有