-TEST 17 for NOIP 暴力有毒(190-300)

头更更大

这个10月完就要去搞NOIP了。。。

10月30天也就3次测试。。。为保佑进省一我还是每次测试玩都写个总结。。


。。。第三题炸了10分。。还能接受。
第一题水题区间DP。
第二题暴力又可以过100?????
第三题不老实的暴力30分。

从本周开始凡是比赛模板禁用!!

下面面详细解答:

T1(100/100):活动安排

problem

题意
给你一些的区间,求最多能让多少区间满足任意两个区间没有交集。
样例

  • 输入
    4
    07:30 08:30
    08:30 10:00
    08:00 12:00
    14:00 15:00

  • 输出
    3

solution

就是一个区间DP,记住是以右端点为第一关键字。

T2(60/100):最佳序列

problem

题意
给你一个序列,问你其中长度在L~R的子序列中,平均值最大是多少。
样例:

  • 输入
    3 2 3
    6 2 8

  • 输出
    5.3333

solution

按理说正解是前缀和加单调队列优化的。。。
但是WYW大佬强行把暴力搞成了正解:只要你理解为什么只用枚举长度在L~min(2*L,R)之间的序列就行。

T3(30/100):回文子串

给你两个字符串,让你按顺序把它们的字母组成一个新串,问你在所有的新串中包含的最长回文字串的长度是多少。

problem

  • 输入
    CLEVER
    JAVA

  • 输出
    6

solution

emm…都知道是道DP但是状态转移很难写。。。。。
以下的分析来自GYR大佬:
状态转移开4维,【bool】dp[i][j][k][l]……表示s串的首位字符位置为a~b的子串与t串的首位字符位置为c~d的子串能否按顺序组成一个回文串。则答案为max((d-c+1)+(b-a+1))。也有可能答案是一个字符串的一个子串,特判一下。
转移的话,由于必须按原顺序,所以这个字符串的首位只能是s[a]或t[c],最末字符只能是s[b]或t[d]。
(一开始GYR用的SPFA然后各种卡常各种判边界来保证转移的合法性。。后来发现判边界不用那么麻烦。)
个人觉得自己打的暴力还是不错。。

感想

多回顾!多练Dp!!多练模板!!!

代码:

T1:

my/std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

int n;
struct node{
    int s,t;
}a[100100];

bool comp(node x,node b)
{
    if(x.t==b.t)return x.s<b.s;
    return x.t<b.t;
}

int h,m;
int f[100100];
int pre=0;

int main()
{
    n=read();
    for(int i=1;i<=n;i++)
    {
        h=read();   m=read();   a[i].s=h*60+m;
        h=read();   m=read();   a[i].t=h*60+m;
    }

    sort(a+1,a+n+1,comp);

    for(int j=1;j<=n;j++)
    {
        if(a[j].s>=pre)f[j]=f[j-1]+1,pre=a[j].t;
        else f[j]=f[j-1];
    }
    cout<<f[n]<<endl;

    return 0;
}

T2

wtf.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

inline long long red()
{
    long long X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

double a[20050];
int N,L,R;
double ans;
double maxx=0;

inline void solve()
{
    for(register int i=L;i<=min(2*L,R);i++)//重点
        for(register int j=i;j<=N;j++)
            ans=max(ans,((double)(a[j]-a[j-i])/i));
}

int main()
{
    N=read();   L=read();   R=read();
    for(register int i=1;i<=N;i++)a[i]=red(),maxx=max(maxx,a[i]),a[i]+=a[i-1];

    if(L==1)ans=(double)(maxx); 
    else solve();

    printf("%0.4lf",ans);
    return 0;
}

下面是规规矩矩的单调队列版(来自ZAY)的题解:

std.cpp

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;

const double eps=1e-6;

int n,L,R;
int a[20010];
double sum[20010],tree[80010];

void read(int &x)
{
    x=0;
    char ch=getchar();
    while(!isdigit(ch)) ch=getchar();
    while(isdigit(ch))
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
}

void build(int l,int r,int x)
{
    if(l==r)
    {
        tree[x]=sum[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,x<<1);
    build(mid+1,r,x<<1|1);
    tree[x]=min(tree[x<<1],tree[x<<1|1]);
}

double get_ans(int l,int r,int L,int R,int x)
{
    if(L<=l && r<=R) return tree[x];
    double ans=20000000010;
    int mid=(l+r)>>1;
    if(L<=mid) ans=min(ans,get_ans(l,mid,L,R,x<<1));
    if(R>mid) ans=min(ans,get_ans(mid+1,r,L,R,x<<1|1));
    return ans;
}

bool check(double x)
{
    for(int i=1;i<=n;++i) sum[i]=sum[i-1]+(double)a[i]-x;
    build(0,n,1);
    for(int i=L;i<=n;++i)
    {
        if(sum[i]-get_ans(0,n,max(0,i-R),i-L,1)>=0) return true;
    }
    return false;
}

int main()
{
    //freopen("lx.in","r",stdin);

    read(n),read(L),read(R);
    for(int i=1;i<=n;++i) read(a[i]);
    double l,r,mid;
    l=0,r=1000010;
    while(r-l>eps)
    {
        mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    printf("%0.4f",l);
    return 0;
}

T3

std.cpp

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;

inline int read()
{
    int X=0,w=1; char ch=0;
    while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
    while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
    return X*w;
}

int f[55][55][55][55];
struct node{
    int a,b,c,d;
    node(int a,int b,int c,int d):a(a),b(b),c(c),d(d){}
};
int vis[55][55][55][55];

char s[55],t[55];
int o1[55],o2[55];
int main()
{
    scanf("%s%s",s+1,t+1);
    int n=strlen(s+1);
    int m=strlen(t+1);
    for(int i=1;i<=n;i++)o1[i]=s[i]-'A';
    for(int i=1;i<=m;i++)o2[i]=t[i]-'A';    

    int ans=0;
    queue<node> q;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=n;k>=i-1;k--)
                for(int l=m;l>=j-1;l--)
                {
                    vis[i][j][k][l] = 1;
                    q.push(node(i,j,k,l));
                }
    while(!q.empty())
    {
        int a=q.front().a;
        int b=q.front().b;
        int c=q.front().c;
        int d=q.front().d;
        q.pop();
        vis[a][b][c][d] = 0;
        int x=f[a][b][c][d];

        if(a<c)
            if(o1[a]==o1[c]&&x+2>f[a+1][b][c-1][d])
            {
                f[a+1][b][c-1][d]=x+2;
                if(!vis[a+1][b][c-1][d])
                {
                    vis[a+1][b][c-1][d]=1;
                    q.push(node(a+1,b,c-1,d));
                }
            }
        if(b<d)
            if(o2[b]==o2[d]&&x+2>f[a][b+1][c][d-1])
            {
                f[a][b+1][c][d-1]=x+2;
                if(!vis[a][b+1][c][d-1])
                {
                    vis[a][b+1][c][d-1]=1;
                    q.push(node(a,b+1,c,d-1));
                }
            }
        if(a<=c&&b<=d)
        {
            if(o1[a]==o2[d]&&x+2>f[a+1][b][c][d-1])
            {
                f[a+1][b][c][d-1]=x+2;
                if(!vis[a+1][b][c][d-1])
                {
                    vis[a+1][b][c][d-1]=1;
                    q.push(node(a+1,b,c,d-1));
                }
            }
            if(o2[b]==o1[c]&&x+2>f[a][b+1][c-1][d])
            {
                f[a][b+1][c-1][d]=x+2;
                if(!vis[a][b+1][c-1][d])
                {
                    vis[a][b+1][c-1][d]=1;
                    q.push(node(a,b+1,c-1,d));
                }
            }
        }
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=n;k>=i-1;k--)
                for(int l=m;l>=j-1;l--)
                {
                    int x=f[i][j][k][l];
                    if(i==k&&j>l)ans=max(ans,x+1);
                    if(i>k&&j==l)ans=max(ans,x+1);
                    if(i>k&&j>l)ans=max(ans,x);             
                }
    cout << ans << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值