9.6-小訓練 三分小板子+單調棧

冬天的睡袋發表於2024-09-06

Codeforces
C. The Legend of Freya the Frog
求最少步數,你可以先比較哪邊會用步數更多,少的那部分只能走0,那麼最終走最大的數的二倍
如果x>y,那麼最後一次y不用走,減1即可
程式碼

#include<bits/stdc++.h>
using namespace std;
#define int long long
int32_t main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin>>t;
    while(t--){
        int a,b,c;
        cin>>a>>b>>c;
      cout<< (int)max(ceil(1.0*b/c)*2,ceil(1.0*a/c)*2-1)<<'\n';
    }
}

D. Satyam and Counting
注意看題目,y>=0&&y<=1,我們可以考慮立的直角三角形和其他情況,立的說明x相同y不同,有n-2個這樣的直角三角形
特殊情況是,中間一個點其他兩個點相差1,並且y跟中間的點不同,上下顛倒是可以的
程式碼

#include<bits/stdc++.h>
using namespace std;
#define PI acos(-1);
#define int long long
#define MAXN 210000
#define debug cout<<"debug:\t"
#define debugn cout<<"debug:\n"
#define enter cout<<"\n"
const int inf=0x3f3f3f3f;
#define N 1000005
const int mod=1e9+7;
struct dian{
    int x,y;
};
void solve(){
    int n;
    cin>>n;
    vector<dian>a(n);
    map<pair<int,int>,int>u;
    map<int,int>v;
    for(int i=0;i<n;i++){
        cin>>a[i].x>>a[i].y;
        u[{a[i].x,a[i].y}]++;
        v[a[i].x]++;
    }
    int sum=0;
    for(int i=0;i<n;i++){
        if(a[i].y==0){
            if(u[{a[i].x-1,1}]!=0 and u[{a[i].x+1,1}]!=0){
                sum++;
            }
        }
        if(a[i].y==1){
            if(u[{a[i].x-1,0}]!=0 and u[{a[i].x+1,0}]!=0){
                sum++;
            }
        }
    }
    for(int i=0;i<=n;i++){
        if(u[{i,1}]!=0 and u[{i,0}]!=0){
            sum+=n-2;
        }
    }
    cout<<sum<<endl;
}
signed main() {


    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

E. Klee's SUPER DUPER LARGE Array!!!
一道比較典型的三分題,可以記下模板,二分也可以做但是需要明確判斷條件
三分(這個函式是V字形,我們只需要比較兩個結果取最小的即可)

#include<bits/stdc++.h>
#define endl '\n'
#define mk make_pair
#define int long long
using namespace std;
typedef long long ll; 
typedef pair<int, int> PII; 
const int N = 2e5+10;
int n,m,k,sum;

int ok(int x){
    int num=x*(m+m+x-1)/2;
    return abs(sum-2*num);
}

void sovle(){
    cin>>n>>m;
    sum=n*(m+m+n-1)/2;
    //cout<<sum<<endl;
    int l=1,r=n;
    while(r-l>10){
        int mid1=(l*2+r)/3;
        int mid2=(r*2+l)/3;
        if(ok(mid1)>ok(mid2)){
            l=mid1;
        }else r=mid2;
    }
    int max1=LLONG_MAX;
    for(int i=l;i<=r;i++){
        max1=min(max1,ok(i));
        //cout<<max1<<endl;
        //cout<<i<<' '<<ok(i)<<endl;
    }
    cout<<max1<<endl;
}


signed main()
{	
    ios::sync_with_stdio(false), cin.tie(0),cout.tie(0); 
    int t = 1; 
    cin>>t;
    while (t --){
        sovle();
    }

    return 0;
}

二分(注意比較條件應該是兩邊的大小進行比較而不是差值)


#include <bits/stdc++.h>

using namespace std;

#define int  long long

int k,n;

int32_t main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin>>t;
    while(t--){
        int ans=0;

        cin>>n>>k;
        int l=k,r=k+n-1;
        int sum=(l+r)*n/2;
        while(l<=r){
          int mid =(l+r)/2;
          int L=(k+mid)*(mid-k+1)/2;
          int R=sum-L;
          if(L>=R){
              ans=mid;
              r=mid-1;
          }else
              l=mid+1;
        }
        if (ans == k) {
            cout << k * 2 - sum << '\n';
        } else {
            cout << min((k + ans) * (ans - k + 1) - sum, sum - (k + ans - 1) * (ans - k)) << '\n';
        }
    }




    return 0;
}

P5788 【模板】單調棧
單調棧的一個板子題,更好理解,注意先!stk.empty(),並且一起處理最大或者最小與一般情況,輸出順序等問題

#include <bits/stdc++.h>

using namespace std;

#define int  long long


int32_t main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin>>n;
    vector<int>v(n+1);
    int maxx=0;
    for (int i = 1; i <=n ; ++i) {
        cin>>v[i];

    }

    stack<pair<int,int>>stk;
    vector<int>ans(n+1);
    int j=1;
    for(int i=n;i>=1;i--){

            while(!stk.empty()&&v[i]>=stk.top().first){
                stk.pop();
            }
            ans[j++]=stk.empty()?0:stk.top().second;
            stk.push(make_pair(v[i],i));

    }
    for(int i=n;i>=1;i--)cout<<ans[i]<<' ';

    return 0;
}

相關文章