Loading

题解-CF360

CF360

质量不错,难度不高的良心场。


CF360A Levko and Array Recovery

luogu

注意到 \(n,m\) 很小,可以先求出每刻每个点的加值。

然后通过区间最值可以得到原最值。

于是构成了一个满足 \(\le\) 最值的原序列,带回去验证是否存在最值即可。


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int N=5e3;
int n,m,a[N],c[N],b[N][4],d[N];

//Main
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>m;
    R(i,n) a[i]=int(1e9);
    R(i,m){
        R(t,4) cin>>b[i][t];
        --b[i][0],--b[i][1];
    }
    R(i,m){
        if(b[i][0]) for(int j=b[i][1];j<b[i][2];++j) a[j]=min(a[j],b[i][3]-d[j]);
        else for(int j=b[i][1];j<b[i][2];++j) d[j]+=b[i][3];
    }
    R(i,n) c[i]=a[i];
    R(i,m){
        if(b[i][0]){
            int mx=-iinf;
            for(int j=b[i][1];j<b[i][2];++j) mx=max(mx,c[j]);
            if(mx!=b[i][3]) return !(cout<<"NO\n");
        } else for(int j=b[i][1];j<b[i][2];++j) c[j]+=b[i][3];
    }
    cout<<"YES\n";
    R(i,n) cout<<a[i]<<' ';
    cout<<'\n';
    return 0;
}

CF360B Levko and Array

luogu

相当于要留下 \(n-m\) 个,先二分答案 \(x\),然后 dp

  • \(f(i)\) 表示以选 \(a_i\) 结尾最多选几个。

  • \[f(i)=\max_{j<i,x(i-j)\ge |a_i-a_j|}\{f(j)+1\} \]

然后看看存不存在 \(f(i)\ge n-m\) 即可。


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int N=2000;
int n,m,a[N],f[N];

//Function
bool check(ll mid){
    // cout<<"mid="<<mid<<'\n';
    R(i,n) f[i]=1;
    R(i,n)R(j,i)if(mid*(i-j)>=abs(a[i]-a[j]))
        f[i]=max(f[i],f[j]+1);
    // R(i,n) cout<<f[i]<<' '; cout<<'\n';
    R(i,n)if(f[i]>=m) return true;
    // cout<<"false\n";
    return false;
}

//Main
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>m,m=n-m;
    R(i,n) cin>>a[i];
    ll l=-1,r=2e9+1;
    while(r-l>1){
        ll mid=(l+r)>>1;
        if(check(mid)) r=mid;
        else l=mid;
    }
    cout<<r<<'\n';
    return 0;
}

CF360C Levko and Strings

luogu

挺巧妙 \(+\) 玄学的计数题。

在每个 \(t\) 的子串中第一个 \(>s\) 的地方统计它的贡献。

\(f(i,x)\) 表示到第 \(i\) 个字母, 有 \(x\) 个子串的方案数。

  1. 如果 \(t_i>s_i\),枚举 \(j<i\),表示 \([j+1,i)\) 这段 \(t_i=s_i\)
    • \[f(i,x)\leftarrow (25-s_i)f(j,x-(n-i+1)(i-j-1)) \]

    • 这段可以暴力枚举,最终复杂度 \(\Theta(n^2\log n)\)
  2. 如果 \(t_i<s_i\),同样枚举 \(j<i\)
    • \[f(i,x)\leftarrow s_i\cdot f(j,x) \]

    • 这段可以前缀和。

然后答案就是 \(\sum_{i=0}^n f(i,k)\)


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int N=2e3+1,mod=1e9+7;
int n,m,f[N][N],sm[N|1][N];
string s;

//Math
int& mod_s(int &x){return x<mod?x:x-=mod;}
int& mod_p(int &x){return x<0?x+=mod:x;}

//Main
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>m>>s,**f=1;
    R(j,m+1) mod_s(sm[1][j]=sm[0][j]+f[0][j]);
    R(i,n){
        L(t,i+1)R(j,m+1-(i+1-t)*(n-i)){
            f[i+1][j+(i+1-t)*(n-i)]=(1ll*(25-
            (s[i]-'a'))*f[t][j]+f[i+1][j+(i+1-t)*(n-i)])%mod;
        }
        R(j,m+1) f[i+1][j]=(1ll*sm[i+1][j]*(s[i]-'a')+f[i+1][j])%mod;
        R(j,m+1) mod_s(sm[i+2][j]=sm[i+1][j]+f[i+1][j]);
    }
    // R(i,n+1)R(j,m+1) cout<<f[i][j]<<" \n"[j==m];
    int ns=0;
    R(i,n+1) mod_s(ns+=f[i][m]);
    cout<<ns<<'\n';
    return 0;
}

CF360D Levko and Sets

luogu

题解-CF360D Levko and Sets


CF360E Levko and Game

luogu

可以先把所有边 \(i\) 权设为 \(r_i\),发现把 \(r_i\) 改为 \(l_i\),总是因为 \(s_1\)\(a_i\)\(s_2\)\(a_i\) 更近,目的是使最短路必经 \(a_i\)

所以可以跑最多 \(k\)dijkstra:每次找到还没被降权且 \(s_1\)\(a_i\)\(s_2\)\(a_i\) 更近的边降权,如果 \(s_1\)\(t\)\(s_2\)\(t\) 更近或者一轮中没有降权过,就 break

最后直接比较 \(s_1\)\(t\)\(s_2\)\(t\) 的距离即可。


#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
#define x first
#define y second
#define bg begin()
#define ed end()
#define pb push_back
#define mp make_pair
#define sz(a) int((a).size())
#define R(i,n) for(int i(0);i<(n);++i)
#define L(i,n) for(int i((n)-1);i>=0;--i)
const int iinf=0x3f3f3f3f;
const ll linf=0x3f3f3f3f3f3f3f3f;

//Data
const int N=1e4,me_N=100;
int n,ce_n,me_n,a,b,t,me[me_N][5];
bool low[me_N];

//Graph
vector<int> adj[N],to,we;
int adde(int u,int v,int w){
    int e_i=sz(to);
    adj[u].pb(e_i),to.pb(v),we.pb(w);
    return e_i;
}
ll a_dis[N],b_dis[N]; bool vis[N];
priority_queue<pair<ll,int>> q;
void dijkstra(int s,ll* dis){
    R(u,n) dis[u]=linf,vis[u]=false;
    q.push(mp(-(dis[s]=0),s));
    while(sz(q)){
        int u=q.top().y; q.pop();
        if(vis[u]) continue; vis[u]=true;
        for(int i:adj[u])if(dis[to[i]]>dis[u]+we[i])
            q.push(mp(-(dis[to[i]]=dis[u]+we[i]),to[i]));
    }
}

//Main
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>n>>ce_n>>me_n>>a>>b>>t,--a,--b,--t;
    R(i,ce_n){
        int u,v,w;
        cin>>u>>v>>w,--u,--v;
        adde(u,v,w);
    }
    R(i,me_n){
        R(t,4) cin>>me[i][t];
        R(t,2) --me[i][t];
        me[i][4]=adde(me[i][0],me[i][1],me[i][3]);
    }
    while(true){
        dijkstra(a,a_dis),dijkstra(b,b_dis);
        if(a_dis[t]<b_dis[t]) break;
        int move=0;
        R(i,me_n)if(!low[i]&&a_dis[me[i][0]]<b_dis[me[i][0]])
            ++move,low[i]=true,we[me[i][4]]=me[i][2];
        if(!move) break;
    }
    if(a_dis[t]<=b_dis[t]){
        cout<<(a_dis[t]==b_dis[t]?"DRAW\n":"WIN\n");
        R(i,me_n) cout<<(low[i]?me[i][2]:me[i][3])<<' ';
        cout<<'\n';
    } else cout<<"LOSE\n"; 
    return 0;
}

posted @ 2020-12-28 15:09  George1123  阅读(99)  评论(0编辑  收藏  举报