1.按结尾从小到大排序:区间选择,区间选点
例题(区间选点)洛谷1250种树
#include<iostream> #include<cstdio> using namespace std; struct strage{ int kw; int jw; int t; }a[30001],temp; int main(){ int n,h,i,j,k,sum=0; int za[30001]={0}; scanf("%d%d",&n,&h); for(i=1;i<=h;i++) scanf("%d%d%d",&a[i].kw,&a[i].jw,&a[i].t); for(i=1;i<h;i++) for(j=i+1;j<=h;j++) if(a[i].jw>a[j].jw){temp=a[i];a[i]=a[j];a[j]=temp;} for(i=1;i<=h;i++) { for(j=a[i].kw;j<=a[i].jw;j++) if(za[j]==1) a[i].t--; k=a[i].t; if(k>0){ for(j=a[i].jw;j>=a[i].kw;j--) if(za[j]==0) { za[j]=1; k--; if(k==0)break; } } } for(i=1;i<=n;i++)if(za[i]==1)sum++; printf("%d",sum); return 0; }
2.开头从小到大排序:区间覆盖
3.可反悔的贪心
做法:1.建立模拟双向链表(记录前一个和后一个)
2.当将一个点从优先队列取出时,标记左右两点访问过,更新双向链表,并将左点权+右点权-当前点权入队
例题P1792
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<queue> #include<cstring> #define N 200007 using namespace std; struct tu { int val,l,r; }p[N]; struct node { int val,pos; bool operator<(const node &x) const { return val<x.val; } }; int n,m,ans; bool vis[N]; priority_queue<node> q; void dui(int x) { p[x].l=p[p[x].l].l; p[x].r=p[p[x].r].r; p[p[x].l].r=x; p[p[x].r].l=x; } int main() { scanf("%d%d",&n,&m); if(n<m*2) { printf("Error!"); return 0; } for(int i=1;i<=n;++i) { scanf("%d",&p[i].val); p[i].l=i-1; p[i].r=i+1; q.push((node){p[i].val,i}); } p[1].l=n,p[n].r=1; for(int i=1;i<=m;++i) { while(vis[q.top().pos]) q.pop(); node now=q.top(); q.pop(); ans+=now.val; vis[p[now.pos].l]=vis[p[now.pos].r]=1; p[now.pos].val=p[p[now.pos].l].val+p[p[now.pos].r].val-p[now.pos].val; q.push((node){p[now.pos].val,now.pos}); dui(now.pos); } printf("%d",ans); return 0; }
还是去手推一下贪心策略,以上只是几种经典题型