2019多校 7.22

6578 Blank

比赛的时候一下子想出来 O ( n 4 ) O(n^4) O(n4)
自己太蠢了,写的是有16常数的 O ( n 4 ) O(n^4) O(n4)
f [ a ] [ b ] [ c ] [ d ] [ 4 ] f[a][b][c][d][4] f[a][b][c][d][4] a = i a=i a=i剩下三个为bcd时的方案数
没想到其实不用管最后一个是谁,开了 [ 0...3 ] [0...3] [0...3]记录
其实不用管最后一个是谁,并将abcd排序即可
时间复杂度 O ( n 4 ) O(n^4) O(n4),滚动数组空间复杂度 O ( n 3 ) O(n^3) O(n3)

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
typedef long long s64;

const int M=1e2+5;
const int mod=998244353;
int n,m;
int l[M],r[M],x_[M];
int f[2][M][M][M];

inline void inc(int &x,int y) {x+=y,x-=x>=mod?mod:0;}

int main() {
     //freopen("a.txt","r",stdin);
     int test_;
     scanf("%d",&test_);
     while (test_--) {
          scanf("%d%d",&n,&m);
          rep(i,1,m) scanf("%d%d%d",l+i,r+i,x_+i);

          rep(i,1,m) {
               rep(j,i+1,m) if(r[j]<r[i]) {
                    swap(r[i],r[j]);
                    swap(l[i],l[j]);
                    swap(x_[i],x_[j]);
               }
          }

          f[0][0][0][0]=1;
          int opt=0;
          int head_=0;
          rep(i,1,n) {
               opt^=1;
               rep(a,0,i-1) rep(b,0,a) rep(c,0,b) {
                    int num=f[opt^1][a][b][c];
                    f[opt^1][a][b][c]=0;
                    if(num) {
                         inc(f[opt][a][b][c],num);//0
                         inc(f[opt][i-1][b][c],num);//1
                         inc(f[opt][i-1][a][c],num); //2
                         inc(f[opt][i-1][a][b],num);//3
                    }
               }

               while (head_<m&&r[head_+1]==i) {
                    ++head_;
                    rep(a,0,i) rep(b,0,a) rep(c,0,b) {
                         if(!f[opt][a][b][c]) continue;
                         int cnt=1;
                         cnt+=a>=l[head_];
                         cnt+=b>=l[head_];
                         cnt+=c>=l[head_];
                         if(cnt!=x_[head_]) f[opt][a][b][c]=0;
                    }
               }
          }

          int ans=0;
          rep(a,0,n) rep(b,0,a) rep(c,0,b) inc(ans,f[opt][a][b][c]);
          cout<<ans<<endl;

          memset(f[opt],0,sizeof(f[opt]));
     }
}

6581 Vacation

二分答案+check
二分时间,算每个人到达的位置,满足i不能超过i+1即可

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
typedef long long s64;

const int M=1e5+5;
int n;
int len[M],way[M],spe[M];
double dis[M];


bool check(double t) {
    dis[n]=way[n]-spe[n]*t;
    per(i,n-1,1) {
        dis[i]=way[i]-spe[i]*t;
        if(dis[i]<dis[i+1]+len[i+1]) dis[i]=dis[i+1]+len[i+1];
    }
    return dis[1]<0;
}

int main() {
    //freopen("a.txt","r",stdin);
    //freopen("c.out","w",stdout);

    while (scanf("%d",&n)==1) {
        ++n;
        rep(i,1,n) scanf("%d",len+i);
        rep(i,1,n) scanf("%d",way+i);
        rep(i,1,n) scanf("%d",spe+i);

        double l=0,r=1e9,mid;
        rep(i,1,100) {
            mid=(l+r)*0.5;
            if(check(mid)) r=mid;
            else l=mid;
        }
        printf("%.10f\n",r);
     }
}

6586 String

一开始看成子串。。。
贪心思路,顺次枚举第i个字母,check是否可行
显然从头开始选最靠前的字母
剩下的就要check a i ϵ [ l i , r i ] a_ {i} \epsilon [l_{i},r_{i}] aiϵ[li,ri]即可
细节一定要自己写对拍

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
//#include <bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,l,r) for(int i=l;i>=r;--i)
using namespace std;
typedef long long s64;

const int M=3e5+5;
int n;
int shu[30];
int sum[M][30];
int L[M],R[M],len;
int nxt[M][30];
char s[M];

bool check(int hav,int x) {
    rep(i,0,25) if(shu[i]>R[i]) return 0;

    rep(i,0,25) if(L[i]-shu[i]>sum[n][i]-sum[x-1][i]) return 0;

    int tot=0;
    rep(i,0,25) tot+=max(0,L[i]-shu[i]);
    if(tot>len-hav) return 0;

    tot=0;
    rep(i,0,25) tot+=min(sum[n][i]-sum[x-1][i],R[i]-shu[i]);
    return tot>=len-hav;
}

int main() {
   // freopen("a.txt","r",stdin);
//    freopen("c.out","w",stdout);

    while (scanf("%s",s+1)==1) {
        memset(shu,0,sizeof(shu));

        scanf("%d",&len);
        n=strlen(s+1);
        rep(i,0,25) scanf("%d%d",L+i,R+i);

        bool not_=0;
        rep(i,0,25) {
            if(L[i]>R[i]) not_=1;
        }
        if(not_) {
            puts("-1");
            continue;
        }
        int kkkk=0;
        rep(i,0,25) kkkk+=R[i];
        if(kkkk<len) {
            puts("-1");
            continue;
        }


        rep(i,1,n) {
            rep(j,0,25) sum[i][j]=sum[i-1][j];
            ++sum[i][s[i]-'a'];
        }

        memset(nxt[n+1],0,sizeof(nxt[n+1]));
        per(i,n,1) {
            rep(j,0,25) nxt[i][j]=nxt[i+1][j];
            nxt[i][s[i]-'a']=i;
        }

        bool vis=0;
        rep(i,0,25) {
            ++shu[i];
            if(nxt[1][i]&&check(1,nxt[1][i]+1)) {
                vis=1;break;
            }
            --shu[i];
        }
        memset(shu,0,sizeof(shu));

        if(!vis) puts("-1");
        else {
            int pre=1;
            rep(i,1,len) {
                rep(j,0,25) {
                    if(!nxt[pre][j]) continue;
                    ++shu[j];
                    if(check(i,nxt[pre][j]+1)) {
                        putchar('a'+j);
                        pre=nxt[pre][j]+1;
                        break;
                    }
                    --shu[j];
                }
            }
            puts("");
        }
     }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值