New:
n个物品要在两个机器上加工 时间分别为ai bi 必须现在第一台机器上加工 求最短加工时间
Johnson算法:
N1为a<b物品集合 N2为a>=b物品集合
N1物品按a升序排序 N2按b降序排序 N1接N2为最优顺序
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,res,a[MAXN],b[MAXN],id[MAXN],mn[MAXN],ans[MAXN]; 21 int main() 22 { 23 n=read(); 24 for(int i=1;i<=n;i++) id[i]=i,a[i]=read(); 25 for(int i=1;i<=n;i++) mn[i]=min(a[i],b[i]=read()); 26 for(int i=1;i<=n;i++) 27 for(int j=i+1;j<=n;j++) 28 if(mn[i]>mn[j]) {swap(mn[i],mn[j]);swap(id[i],id[j]);} 29 for(int i=1,s=0,t=n+1;i<=n;i++) 30 if(mn[i]==a[id[i]]) ans[++s]=id[i]; 31 else ans[--t]=id[i]; 32 for(int i=1,s=0;i<=n;i++) 33 s+=a[ans[i]],res=max(res+b[ans[i]],s+b[ans[i]]); 34 printf("%d\n%d",res,ans[1]); 35 for(int i=2;i<=n;i++) printf(" %d",ans[i]); 36 }
T1 数列极差
题目大意:
n个数的集合 每次可以取出两个数a b在集合中删除 加入a*b+1
求只有最后一个数时,最后一个数的最大值与最小值之差
思路:
建立大根堆 每次取出堆顶可以得到最小值
建立小根堆 每次取出堆顶可以得到最大值
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010101 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,a[MAXN],x,y; 21 priority_queue <int> q1; 22 priority_queue <int,vector<int>,greater<int> > q2; 23 int main() 24 { 25 n=read(); 26 for(int i=1;i<=n;i++) {a[i]=read();q1.push(a[i]);q2.push(a[i]);} 27 for(int i=1;i<n;i++) 28 { 29 x=q1.top();q1.pop(); 30 y=q1.top();q1.pop(); 31 q1.push(x*y+1); 32 x=q2.top();q2.pop(); 33 y=q2.top();q2.pop(); 34 q2.push(x*y+1); 35 } 36 printf("%d",q2.top()-q1.top()); 37 }
T2 数列分段
题目大意:
n个数的数列 分成连续若干段 每段和<=m 求最少段数
思路:
只要可以加入下一个数就加入 暴力即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010101 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,m,a[MAXN],ans; 21 int main() 22 { 23 n=read(),m=read(); 24 for(int i=1;i<=n;i++) a[i]=read(); 25 for(int i=1,s=0;i<=n;i++) 26 { 27 if(s+a[i]>m) ans++,s=0; 28 s+=a[i]; 29 } 30 printf("%d",ans+1); 31 }
T3 线段
题目大意:
n条线段 求k个不相交的线段 求最大k
思路:
右端点排序
从第一个线段开始求最大值即为所求
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010101 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,ed,ans=1; 21 struct data {int x,y;}g[MAXN]; 22 bool cmp(data a,data b) {return a.y<b.y;} 23 int main() 24 { 25 n=read(); 26 for(int i=1;i<=n;i++) g[i].x=read(),g[i].y=read(); 27 sort(g+1,g+n+1,cmp); 28 for(int i=2,ed=g[1].y;i<=n;i++) 29 if(g[i].x>=ed) ans++,ed=g[i].y; 30 printf("%d",ans); 31 }
T4 家庭作业
题目大意:
n个作业 每个有学分和截止日期 每天只能做一项作业
每个作业必须在截止日期前完成才能获得学分 求最大学分
思路:
1 按照截止日期倒序 遇到一个作业就加入大根堆 每天做大根堆的堆顶 nlogn
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010101 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,ans,mx=-inf; 21 struct data {int val,t;}g[MAXN]; 22 bool cmp(data a,data b) {return a.t>b.t;} 23 int main() 24 { 25 n=read(); 26 priority_queue <int> q;ans=0; 27 for(int i=1;i<=n;i++) g[i].t=read(),g[i].val=read(),mx=max(mx,g[i].val); 28 if(mx<0) {puts("0");return 0;} 29 sort(g+1,g+n+1,cmp); 30 for(int i=g[1].t,pos=1;i>=1;i--) 31 { 32 while(pos<=n&&g[pos].t>=i) q.push(g[pos++].val); 33 if(!q.empty()) {ans+=q.top();q.pop();} 34 } 35 printf("%d\n",ans); 36 }
2 按照学分排序 每次把这个作业放到截止日期前最靠后的位置去做 线段树 nlogn
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010101 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int mx[MAXN<<2]; 21 void build(int k,int l,int r) 22 { 23 mx[k]=r;if(l==r) return ; 24 int mid=(l+r)>>1; 25 build(k<<1,l,mid);build(k<<1|1,mid+1,r); 26 } 27 int query(int k,int l,int r,int a,int b) 28 { 29 if(l==a&&r==b) return mx[k]; 30 int mid=(l+r)>>1; 31 if(mid>=b) return query(k<<1,l,mid,a,b); 32 else if(mid<a) return query(k<<1|1,mid+1,r,a,b); 33 else return max(query(k<<1,l,mid,a,mid),query(k<<1|1,mid+1,r,mid+1,b)); 34 } 35 void mdf(int k,int l,int r,int x) 36 { 37 if(l==r) {mx[k]=-1;return ;} 38 int mid=(l+r)>>1; 39 if(mid>=x) mdf(k<<1,l,mid,x); 40 else mdf(k<<1|1,mid+1,r,x); 41 mx[k]=max(mx[k<<1],mx[k<<1|1]); 42 } 43 int n,ans,x,tim; 44 struct data {int val,t;}g[MAXN]; 45 bool cmp(data a,data b) {return a.val>b.val;} 46 int main() 47 { 48 n=read(); 49 if(!n) {puts("0");return 0;} 50 for(int i=1;i<=n;i++) g[i].t=read(),g[i].val=read(),tim=max(g[i].t,tim); 51 sort(g+1,g+n+1,cmp);build(1,1,tim); 52 for(int i=1;i<=n;i++) 53 { 54 if((x=query(1,1,tim,1,g[i].t))==-1) continue; 55 ans+=g[i].val;mdf(1,1,tim,x); 56 } 57 printf("%d\n",ans); 58 }
3 在2的基础上进行改进 使用链表+压缩路径查找最后可以使用的位置
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010101 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,ans,tim,x,f[MAXN]; 21 int find(int x) {return x==f[x]?x:f[x]=find(f[x]);} 22 struct data {int val,t;}g[MAXN]; 23 bool cmp(data a,data b) {return a.val>b.val;} 24 int main() 25 { 26 n=read(); 27 if(!n) {puts("0");return 0;} 28 for(int i=1;i<=n;i++) g[i].t=read(),g[i].val=read(),tim=max(tim,g[i].t); 29 for(int i=1;i<=tim;i++) f[i]=i; 30 sort(g+1,g+n+1,cmp); 31 for(int i=1;i<=n;i++) 32 { 33 x=find(g[i].t); 34 if(x>0) f[x]=x-1,ans+=g[i].val; 35 } 36 printf("%d\n",ans); 37 }
T5 钓鱼
题目大意:
12*H个单位时间,有n个鱼池在一条直线上,一开始在1的位置,可以选择在某些鱼池上钓鱼,但是如果持续在一个鱼池上钓鱼钓鱼速度会线性减少
初始每个时间单位钓fi条,然后下一个时间单位钓fi-di条,再下一个fi-di-di条
每个鱼池和他下一个鱼池的距离是ti个时间单位,最后你可以停到任意一个鱼池上
问最多钓多少条鱼,然后输出在个鱼池的停留时间和最多的鱼数
思路:
枚举最后停留的池塘 减去所有路程的时间
然后找到这些池塘中剩余鱼数量最多的
钓一个单位,减去d i
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 1010 12 #define eps 1e-3 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,k,h,tt,mx,f[MAXN],d[MAXN],t[MAXN],a[MAXN],ans,res; 22 int main() 23 { 24 n=read(),mx=0,h=read()*12; 25 for(int i=1;i<=n;i++) f[i]=read(); 26 for(int i=1;i<=n;i++) d[i]=read(); 27 for(int i=1;i<=n-1;i++) t[i]=read(); 28 for(int s=0,x,i=1;i<=n;i++) 29 { 30 s+=t[i-1],res=0,x=h-s; 31 for(int j=1;j<=i;j++) a[j]=f[j]; 32 for(int j=1;j<=x;j++) 33 { 34 mx=a[1],tt=1; 35 for(int k=2;k<=i;k++) 36 if(a[k]>mx) mx=a[k],tt=k; 37 a[tt]-=d[tt],res+=mx; 38 if(a[tt]<0) a[tt]=0; 39 } 40 ans=max(ans,res); 41 } 42 printf("%d",ans); 43 }
T6 糖果传递