『GTOI』Round 1

P13594 『GTOI - 1A』Bath

贪心,维护当前区间,当不能合法时就调整一次

#include<bits/stdc++.h> 
#define ft first
#define se second
using namespace std;
#define int long long
const int N=100010;
int n,s,L,R;
pair<int,int> q[N];
vector<int> p;

pair<int,int> insec(int a,int b,int c,int d){
    int r1=max(a,c);int r2=min(b,d);
    if(r1>r2)return {-1,-1};
    return {r1,r2};
}
signed main( )
{
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
    cin>>n>>s;
    cin>>L>>R;
    for(int i=1;i<=n;i++){
        cin>>q[i].ft>>q[i].se;
    }
    sort(q+1,q+n+1);
    for(int i=1;i<=n;i++){
        int j=i;int s=0;
        while(j<=n&&q[j].ft==q[i].ft){
            s+=q[j].se;
            j++;
        }p.push_back(s);
        j--;
        i=j;
        
    }

    int l=s;int r=s;int ans=0;
    for(auto x:p){
        l+=x;r+=x;
        auto [tl,tr]=insec(l,r,L,R);
        if(tl==-1){
            l=L;r=R;
            ans++;
        }else {
            l=tl;r=tr;
        }
        //cout<<"now"<<l<<" "<<r<<endl;
    }
    cout<<ans;
    
    return 0;
}

P13595 『GTOI - 1B』筝

调整可以使一个区间合法
发现存在一个最优方案为只调整相邻的x=y+1(x=y-1),否则假设有最优解存在将不相邻的x调整成y,替换为x->x+1 x+1->x+2,总代价最多是y-x,方案不劣
所以得到的每一个操作对应的区间是[mp[x],mp[x+-1]],要从这些操作中选出数量最少的覆盖整个数组
之后就是区间覆盖问题

#include<bits/stdc++.h>
using namespace std;
#define ft first
#define se second
const int N=10000010;
int a[N];int mp[N];
vector<pair<int,int>> seg;
/*
7
7 2 6 5 4 3 1
*/

signed main(){
    std::ios::sync_with_stdio(false);
    int n;cin>>n;
    for(int i=1;i<=n;i++){cin>>a[i];mp[a[i]]=i;}

    for(int i=1;i<=n;i++){
        int r1=-1;int r2=-1;
        if(a[i]>1){
            r1=mp[a[i]-1];
            if(r1>=i);else r1=-1;
        }
        if(a[i]<n){
            r2=mp[a[i]+1];
            if(r2>=i);else r2=-1;
        }
        if(r1>r2)swap(r1,r2);
        if(r1!=-1)seg.push_back({i,r1});
        if(r2!=-1)seg.push_back({i,r2});
    }
    //自然就是按照左端点排好的
    //sort(seg.begin(),seg.end());
    int nowr=0;int ans=0;
    for(int i=0;i<seg.size();i++){
        if(nowr>=n)break;
        int j=i;int tr=nowr;
        while(j<seg.size()&&seg[j].ft<=nowr+1){tr=max(tr,seg[j].se);j++;}j--;
        nowr=tr;ans++;
        i=j;
    }
    cout<<ans;

}
posted @ 2025-08-17 19:30  arin876  阅读(20)  评论(0)    收藏  举报