csp-s模擬測試104「中間值·最小值」

考試時的記錄(t1)c++

//12 14 18
//13 15 17 18鍋
//二分套二分不可行
//1 3 5 7 9
//2 4 6 8 10
//倍增/分塊會被卡
//主席樹須要帶修改
//線段樹根本維護不了
//set須要得知序列
//可持久化set?
//莫隊複雜度不對n^(5/3)
//分塊維護不了

以爲t1根本無法搞,主要是二分套二分被我否決了git

原本打了個二分套二分,而後一拍就掛ide

後來就調,以爲很噁心函數

最後發現我二分套二分瑋了優化

我二分策略是二分第一段長度,而後在第二段裏lower_bound,upper_bound找到<第一段二分位置的值的第一位置,和>第一段二分位置值最後一個位置???spa

幃的code

12 14 18blog

13 15 17 18ci

裏15是mid我查不到get

其實暴力能夠直接二分答案,而後在兩段裏--upper_bound找到<=的值,

我這不是弱智嗎

簡單題複雜化,能力max

中間值

題解

$n*{log}^2$就是上面說的直接二分答案,兩段裏--upper_bound找到<=的值

優化成$n*log$就是二分第一段位置,找到第二段對應位置(莫名和考試時葦掉的思路類似)

看是否符合,若是二分地一段找到一個x,對應第二段位置y,符合a[x]>=b[y-1]&&a[x]<=b[r+1]就是知足條件的

代碼

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1111111
ll n,m;
ll a[A],b[A];
//ll read(){ll x;cin>>x;return x;}
ll read(){
    ll x=0,f=1;char c=getchar();
    while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
ll jud(ll x,ll l,ll r){
    if(x>r) return n+1;
    if(x<l) return 0;
    return x;
}
ll erf1(ll l1,ll r1,ll l2,ll r2){
    ll len=(r2-l2+1+r1-l1+1+1)/2;
    ll l=l1,r=min(r1,l1+len-1);
    while(l<=r){
        ll mid=(l+r)>>1;
        if(b[jud(l2+len+l1-mid-2,l2,r2)]<=a[mid]&&b[jud(l2+len-(mid-l1+1),l2,r2)]>=a[mid]) {printf("%lld\n",a[mid]);return 1;}
        if(b[jud(l2+len+l1-mid-2,l2,r2)]>a[mid]) l=mid+1;
        else r=mid-1;
    }
    return 0;
}
ll erf2(ll l1,ll r1,ll l2,ll r2){
    ll len=(r2-l2+1+r1-l1+1+1)/2;
    ll l=l2,r=min(r2,l2+len-1);
    while(l<=r){
        ll mid=(l+r)>>1;
        if(a[jud(l2+len+l1-mid-2,l1,r1)]<=b[mid]&&a[jud(l2+len-(mid-l1+1),l1,r1)]>=b[mid]) {printf("%lld\n",b[mid]);return 1;}
        if(a[jud(l2+len+l1-mid-2,l1,r1)]>b[mid]) l=mid+1;
        else r=mid-1;
    }
    return 0;
}
int main(){
    freopen("median.in","r",stdin);
    freopen("median.out","w",stdout);
    n=read(),m=read();
    for(ll i=1;i<=n;i++)
        a[i]=read();
    for(ll i=1;i<=n;i++)
        b[i]=read();
    a[n+1]=b[n+1]=123456798101112;
    for(ll i=1;i<=m;i++){
        ll opt=read();
        if(opt==1){
            ll x=read(),y=read(),z=read();
            if(x==0) a[y]=z;
            else b[y]=z;
        }
        else {
            ll l1=read(),r1=read(),l2=read(),r2=read();
            if(!erf1(l1,r1,l2,r2)) erf2(l1,r1,l2,r2);
        }
    }
    
}
View Code

最小值

題解

水掉沒臉,

代碼

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define $ 1111111
ll read(){
    ll x=0,f=1;char c=getchar();
    while(!isdigit(c)) {
    if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)){x=x*10+c-'0';c=getchar();}
    return x*f;
}
ll A,B,C,D,n;
ll a[$],f[$]; //627982878638142
//min知足單調性但這個函數不必定知足
int main(){
    freopen("min.in","r",stdin);
    freopen("min.out","w",stdout);
    n=read(),A=read(),B=read(),C=read(),D=read();
    for(ll i=1;i<=n;i++){
        a[i]=read();
    }
    memset(f,-0x7f,sizeof(f));
    f[0]=0;
    for(ll i=1;i<=n;i++){
        ll minn=a[i];
        for(ll j=i-1;j>=max(0ll,i-500);j--){
            minn=min(a[j+1],minn);
            f[i]=max(f[i],f[j]+minn*minn*minn*A+minn*minn*B+minn*C+D);
//            printf("minn*minn*minn*A+minn*minn*B+minn*C+D=%lld\n",minn*minn*minn*A+minn*minn*B+minn*C+D);
//            if(minn*minn*minn*A+minn*minn*B+minn*C+D<0) break;
        }
    }
    printf("%lld\n",f[n]);
}
View Code
相關文章
相關標籤/搜索