Intervals
阿新 • • 發佈:2020-07-28
題目描述
題目大意
其實這題目的大概意思是首先我們可以輸入三個數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; }