9.6-小训练 三分小板子+单调栈

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;
}
posted @ 2024-09-06 00:57  冬天的睡袋  阅读(17)  评论(0编辑  收藏  举报