『一本通』贪心

 《信息学奥赛一本通》提高版题解索引


 

活动安排

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,lst,ans;
 4 struct node{int l,r;}a[1005]; 
 5 bool cmp(node x1,node x2) {return x1.r<x2.r;}
 6 
 7 int main() {
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i++) 
10      scanf("%d%d",&a[i].l,&a[i].r);
11     sort(a+1,a+n+1,cmp);
12     for(int i=1;i<=n;i++) 
13      if(lst<=a[i].l) ans++,lst=a[i].r;
14     printf("%d",ans);
15 }
16 //贪心(结束时间早的优先)

 

种树

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,h,ans;
 4 bool vis[30005];
 5 struct node{int b,e,t;}a[30005];
 6 bool cmp(node x1,node x2) {return x1.e<x2.e;}
 7 
 8 int main() {
 9     scanf("%d%d",&n,&h);
10     for(int i=1;i<=h;i++)
11      scanf("%d%d%d",&a[i].b,&a[i].e,&a[i].t);
12     sort(a+1,a+h+1,cmp);
13     for(int i=1;i<=h;i++) {
14         for(int j=a[i].b;j<=a[i].e;j++)
15          if(vis[j]) a[i].t--;
16         if(a[i].t<=0) continue;
17         ans+=a[i].t;
18         int tot=0;
19         for(int j=a[i].e;j>=a[i].b;j--) {
20             if(!vis[j]) tot++,vis[j]=1;
21             if(tot==a[i].t) break;
22         }
23     }
24     printf("%d",ans);
25 }
26 //贪心(在编号大的路段种树)

 

喷水装置

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int T,n,l,cnt,ans;
 4 double w;
 5 struct node{double l,r;}a[15005];
 6 inline int read() {
 7     int x=0; char c=getchar();
 8     while(c<'0'||c>'9') c=getchar();
 9     while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
10     return x;
11 }
12 bool cmp(node x1,node x2) {return x1.l<x2.l;}
13 
14 int main() {
15     T=read();
16     while(T--) {
17         cnt=ans=0;
18         n=read(),l=read(),w=read()/2.0;
19         for(int i=1;i<=n;i++) {
20             int x=read(); double r=read();
21             if(r<w) continue; 
22             r=sqrt(r*r-w*w); 
23             a[++cnt].l=x-r,a[cnt].r=x+r;
24         }
25         sort(a+1,a+cnt+1,cmp);
26         if(a[1].l>0) {printf("-1\n"); continue;}
27         int i=1; double rst=0; 
28         while(i<=cnt) {
29             double maxx=-1.0;
30             while(a[i].l<=rst&&i<=cnt) maxx=max(maxx,a[i++].r);
31             if(maxx>rst) {
32                 ans++,rst=maxx;
33                 if(rst>=l) break;
34             }else break;
35         }
36         if(rst<l) {printf("-1\n"); continue;}
37         printf("%d\n",ans);
38     }
39 }
40 //贪心(向右拓展能够浇灌的最右端点:rst)

 

加工生产调度

前置技能:johnson算法

 1 #include<bits/stdc++.h>
 2 #define N 1005
 3 using namespace std;
 4 int n,a[N],b[N],ans[N];
 5 struct node{int mi,id;}s[N];
 6 bool cmp(node x1,node x2) {return x1.mi<x2.mi;}
 7 
 8 int main() {
 9     scanf("%d",&n);
10     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
11     for(int i=1;i<=n;i++) {
12         scanf("%d",&b[i]);
13         s[i].mi=min(a[i],b[i]),s[i].id=i;
14     }
15     sort(s+1,s+n+1,cmp);
16     int A=0,B=n+1;
17     for(int i=1;i<=n;i++)
18      if(s[i].mi==a[s[i].id]) ans[++A]=s[i].id;
19      else ans[--B]=s[i].id;
20     int ta=0,tb=0;
21     for(int i=1;i<=n;i++) {
22         ta+=a[ans[i]];
23         tb=max(ta,tb)+b[ans[i]];
24     }
25     printf("%d\n",tb);
26     for(int i=1;i<n;i++) printf("%d ",ans[i]);
27     printf("%d",ans[n]); 
28 }

 

智力大冲浪

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m;
 4 bool vis[505];
 5 struct node{int t,w;}a[505];
 6 bool cmp(node x1,node x2) {return x1.w>x2.w;}
 7 
 8 int main() {
 9     scanf("%d%d",&m,&n);
10     for(int i=1;i<=n;i++) scanf("%d",&a[i].t);
11     for(int i=1;i<=n;i++) scanf("%d",&a[i].w);
12     sort(a+1,a+n+1,cmp);
13     for(int i=1;i<=n;i++) 
14      for(int j=a[i].t;j>=1;j--) {
15         if(!vis[j]) {vis[j]=1; break;}
16         if(j==1) m-=a[i].w;
17      }
18     printf("%d",m);
19 }
20 //贪心(扣款数大的优先完成,所用的时段尽量靠后)

 

数列极差

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 struct cmp{
 4     bool operator()(const int &a,int &b) {
 5         return a>b;
 6     }
 7 };
 8 int n,x;
 9 priority_queue<int>q1; //min
10 priority_queue<int,vector<int>,cmp>q2; //max
11 
12 int main() {
13     scanf("%d",&n);
14     for(int i=1;i<=n;i++) {
15         scanf("%d",&x);
16         q1.push(x); q2.push(x);
17     }
18     for(int i=1;i<n;i++) {
19         int minn=q1.top(); q1.pop();
20         minn*=q1.top(); q1.pop();
21         q1.push(minn+1);
22         int maxx=q2.top(); q2.pop();
23         maxx*=q2.top(); q2.pop();
24         q2.push(maxx+1);
25     }
26     printf("%d",q2.top()-q1.top());
27 }    

 

数列分段

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,m,x,ans;
 4 
 5 int main() {
 6     scanf("%d%d",&n,&m);
 7     int tot=0;
 8     for(int i=1;i<=n;i++) {
 9         scanf("%d",&x);
10         tot+=x;
11         if(tot>m) tot=x,ans++;
12     }
13     printf("%d",ans+1);
14 }

 

线段

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int n,lst=-1,ans;
 4 struct node{int l,r;}a[1000005]; 
 5 bool cmp(node x1,node x2) {return x1.r<x2.r;}
 6 
 7 int main() {
 8     scanf("%d",&n);
 9     for(int i=1;i<=n;i++) 
10      scanf("%d%d",&a[i].l,&a[i].r);
11     sort(a+1,a+n+1,cmp);
12     for(int i=1;i<=n;i++) 
13      if(lst<=a[i].l) ans++,lst=a[i].r;
14     printf("%d",ans);
15 }
16 //同『活动安排』

 

家庭作业

 1 #include<bits/stdc++.h>
 2 #define N 700005
 3 using namespace std;
 4 int n,ans;
 5 bool vis[N],b[N];
 6 struct node{int t,w;}a[1000005];
 7 bool cmp(node x1,node x2) {return x1.w>x2.w;}
 8 
 9 int main() {
10     scanf("%d",&n);
11     for(int i=1;i<=n;i++) 
12      scanf("%d%d",&a[i].t,&a[i].w);
13     sort(a+1,a+n+1,cmp);
14     for(int i=1;i<=n;i++) 
15      for(int j=a[i].t;j>=1;j--) {
16         if(b[j]==1) {b[a[i].t]=1; break;}
17         if(!vis[j]) {vis[j]=1,ans+=a[i].w; break;}
18         if(j==1) b[a[i].t]=1;
19      }
20     printf("%d",ans);
21 }
22 //同【智力大冲浪】

 

钓鱼

 1 #include<bits/stdc++.h>
 2 #define N 105
 3 using namespace std;
 4 int n,h,cnt,ans,a[N],d[N],t[N],f[250];
 5 bool cmp(int x,int y) {return x>y;}
 6 
 7 int main() {
 8     n=read(),h=read()*12;
 9     for(int i=1;i<=n;i++) a[i]=read();
10     for(int i=1;i<=n;i++) d[i]=read();
11     for(int i=2;i<=n;i++) t[i]=read();
12     for(int i=1;i<=n;i++) {
13         if((h-=t[i])<=0) break;
14         for(int j=a[i],k=0;j>0&&k<=h;j-=d[i])
15          f[++cnt]=j,k++;
16         sort(f+1,f+cnt+1,cmp);
17         int sum=0; cnt=min(cnt,h);
18         for(int j=1;j<=cnt;j++) sum+=f[j];
19         ans=max(ans,sum);
20     }
21     printf("%d",ans);
22 }

 

糖果传递

题解

 1 #include<bits/stdc++.h>
 2 #define N 1000005
 3 using namespace std;
 4 long long n,ave,ans,a[N],t[N];
 5 
 6 int main() {
 7     scanf("%lld",&n);
 8     for(int i=1;i<=n;i++) 
 9      scanf("%lld",&a[i]),ave+=a[i];
10     ave/=n;
11     for(int i=1;i<=n;i++) t[i]=t[i-1]+a[i]-ave;
12     sort(t+1,t+n+1);
13     long long midd=t[n/2];
14     for(int i=1;i<=n;i++) ans+=abs(midd-t[i]);
15     printf("%lld",ans);
16 }

 

终于把这个巨坑填了~(严重烂尾)

2019.2.24

 

posted @ 2019-01-07 22:59  YeLingqi  阅读(451)  评论(0编辑  收藏  举报