20240622訓練

junjunccc發表於2024-06-22

檔名是abcd的逆天考試(

算術(a)

題面:
給定一個長度為\(n\)的整數數列\(a_1,\dots,a_n\),求有多少個有序對\((i,j)\)滿足\(i<j\wedge a_ia_j<a_i+a_j\)
題解:
列舉\(j\),有\(a_i(a_j-1)<a_j\),對\(a_j\)分類討論。
\(a_j>1\)\(a_i<a_j/(a_j-1)\),即\(a_i\le 1\)
\(a_j=1\)\(0<1\),即\(a_i\)取任意值。
\(a_j=0\)\(a_i>0\),即\(a_i\ge1\)
\(a_j>1\)\(a_i<a_j/(a_j-1)\),即\(a_i\ge1\)
在列舉的同時統計前面有多少個\(\le1\)\(\ge1\)的即可。
程式碼

#include<cstdio>
#define int long long
int n,a,ans;
signed main(){
    freopen("a.in","r",stdin),freopen("a.out","w",stdout),scanf("%lld",&n);
    for(int i=1,cntle1=0,cntme1=0;i<=n;i++){
        scanf("%lld",&a);
        if(a>1)ans+=cntle1;
        else if(a==1)ans+=i-1;
        else ans+=cntme1;
        if(a<=1)cntle1++;
        if(a>=1)cntme1++;
    }
    return printf("%lld\n",ans),fflush(stdout),fclose(stdin),fclose(stdout),0;
}

刷牆(b)

題面:
\(n\)種顏色的刷子,每個刷子可以刷\([l_i,r_i]\),新顏色會覆蓋舊顏色,可以選擇刷子的順序,求牆上最多有多少種顏色。
題解:
因為點數較小,先離散化,然後動態規劃。
狀態:\(f(i,j)\)表示區間\([i,j]\)內最多有多少種顏色。
輔助函式:\(s(i,j)\)表示區間\([i,j]\)包含了多少種刷子。
轉移方程:

\[f(l,r)=\max_{k\in[l,r)\wedge s(l,k)+s(k+1,r)<s(l,r)}(f(l,k)+f(k+1,r)+1) \]

\([l,r]\)有中經過\([k,k+1]\)的刷子才能更新\(f(l,r)\)
程式碼

#include<cstdio>
#include<algorithm>
const int N=605;
int n,t[N],cnt,l[N],r[N],s[N][N],f[N][N];
inline int find(int x){return std::lower_bound(t+1,t+cnt+1,x)-t;}
inline void tomax(int&x,int y){x<y&&(x=y);}
int main(){
    freopen("b.in","r",stdin),freopen("b.out","w",stdout),scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d",l+i,r+i),t[++cnt]=l[i],t[++cnt]=r[i];
    std::sort(t+1,t+cnt+1),cnt=std::unique(t+1,t+cnt+1)-t-1;
    for(int i=1;i<=n;i++)l[i]=find(l[i]),r[i]=find(r[i]),s[l[i]][r[i]]++;
    for(int len=2;len<=cnt;len++)for(int l=1,r=len;r<=cnt;l++,r++){
        s[l][r]+=s[l+1][r]+s[l][r-1]-s[l+1][r-1];
        for(int i=l;i<r;i++)if(s[l][i]+s[i+1][r]<s[l][r])tomax(f[l][r],f[l][i]+f[i+1][r]+1);
    }
    return printf("%d\n",f[1][cnt]),fflush(stdout),fclose(stdin),fclose(stdout);
}

相關文章