1. 程式人生 > 實用技巧 >Intervals

Intervals

題目描述

題目大意

其實這題目的大概意思是首先我們可以輸入三個數a,b,c這三個數其中的前兩個是一個區間表示在這個區間當中有至少c個數,我們輸入n次這樣的三個數,最後求出在整個區間當中數的最小的個數是多少?

相似題

我認為這道題和種樹差不多

思路(種樹)

貪心,要種樹種得少,就要使一棵樹給多個區間使用,這樣,儘量在重疊區間種樹即可,而重疊位置一定是區間尾部。處理問題時,先按所有區間的結束位置從小到大排序,若結束位置相同,則按開始位置從大到小排序。之後依次處理每個區間,先在第一個區間尾部種滿足要求的樹,對下一個區間,看差多少棵就在該區間尾部種多少。

步驟:

①先按照b[]從小到大快排

②對每個區間依次處理

a.從前到後掃描這個區間,統計點的個數;

b.若沒有超過要求的點數,則從該區間後向前掃描,新增覆蓋點。

③輸出ans

思路(Intervals)

對比種樹我們不難得到這道題目的思路

和種樹可以一樣

程式碼(種樹)

#include<iostream>
using namespace std;
struct line{int s,e,v;}a[5005],mid;
int n,m,used[30005]={0};
void qsort(int L,int r)//快排
{  int i=L,j=r;mid=a[(L+r)/2];
   while(i<=j)
   {  while(a[i].e<mid.e)i++;
      
while(a[j].e>mid.e)j--; if(i<=j)swap(a[i++],a[j--]); } if(L<j)qsort(L,j); if(i<r)qsort(i,r); } void Init() { int i; cin>>n>>m; for(i=1;i<=m;i++)cin>>a[i].s>>a[i].e>>a[i].v; qsort(1,m); } void Solve() { int i,j,k,ans=0; for(i=1;i<=m;i++)//
依次處理m個區間 { k=0; for(j=a[i].s;j<=a[i].e;j++)if(used[j])k++;//統計區間內已標記的數 if(k<a[i].v) for(j=a[i].e;j>=a[i].s;j--) if(!used[j]){used[j]=1;k++;ans++;if(k==a[i].v)break;} } cout<<ans<<endl; } int main() { Init(); Solve(); }

程式碼(Intervals)

#include <bits/stdc++.h>
using namespace std;
struct node{
    int l,r,w;
}e[50010];
int n,ans;
int vis[50010];
bool cmp(node x,node y){
    return x.r<y.r;
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d%d%d",&e[i].l,&e[i].r,&e[i].w);
    sort(e+1,e+n+1,cmp);
    for(int i=1;i<=n;i++){
        int sum=0;
        for(int j=e[i].l;j<=e[i].r;j++) 
            if(vis[j])sum++;
        if(sum>=e[i].w)continue;
        for(int j=e[i].r;j>=e[i].l;j--){
            if(!vis[j])vis[j]=1,sum++,ans++;
            if(sum>=e[i].w)break;
        }
    }
    printf("%d",ans);
    return 0;
}