首页 > 代码库 > HDU 6047 Maximum Sequence(贪心+线段树)
HDU 6047 Maximum Sequence(贪心+线段树)
题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=6047
题目:
Maximum Sequence
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 90 Accepted Submission(s): 44
Problem Description
Steph is extremely obsessed with “sequence problems” that are usually seen on magazines: Given the sequence 11, 23, 30, 35, what is the next number? Steph always finds them too easy for such a genius like himself until one day Klay comes up with a problem and ask him about it.
Given two integer sequences {ai} and {bi} with the same length n, you are to find the next n numbers of {ai}: an+1…a2n. Just like always, there are some restrictions on an+1…a2n: for each number ai, you must choose a number bk from {bi}, and it must satisfy ai≤max{aj-j│bk≤j<i}, and any bk can’t be chosen more than once. Apparently, there are a great many possibilities, so you are required to find max{∑2nn+1ai} modulo 109+7 .
Now Steph finds it too hard to solve the problem, please help him.
Given two integer sequences {ai} and {bi} with the same length n, you are to find the next n numbers of {ai}: an+1…a2n. Just like always, there are some restrictions on an+1…a2n: for each number ai, you must choose a number bk from {bi}, and it must satisfy ai≤max{aj-j│bk≤j<i}, and any bk can’t be chosen more than once. Apparently, there are a great many possibilities, so you are required to find max{∑2nn+1ai} modulo 109+7 .
Now Steph finds it too hard to solve the problem, please help him.
Input
The input contains no more than 20 test cases.
For each test case, the first line consists of one integer n. The next line consists of n integers representing {ai}. And the third line consists of n integers representing {bi}.
1≤n≤250000, n≤a_i≤1500000, 1≤b_i≤n.
For each test case, the first line consists of one integer n. The next line consists of n integers representing {ai}. And the third line consists of n integers representing {bi}.
1≤n≤250000, n≤a_i≤1500000, 1≤b_i≤n.
Output
For each test case, print the answer on one line: max{∑2nn+1ai} modulo 109+7。
Sample Input
4
8 11 8 5
3 1 4 2
Sample Output
27
多校联赛第二场~
题意:
给定一个长度为n的a数组和b数组,要求a[n+1]…a[2*n]的最大总和。 限制条件为ai≤max{aj-j│bk≤j<i}。
思路:
a[j](j>n)是从当前选择的a数组的b[k]个数开始,到最后一个数中选。由于每个b[k]都只能使用一次,我们要可能地把b[k]较大的数留在后面用,因为刚开始a数组只有n个,只有随着每次操作a数组才会增加一个数。
顺着这个思路,我们很自然地先对b数组做一次升序排序,再以b[k]为左区间,a数组当前的个数为右区间,来找最大的a[j]; 因为数据量比较大,我们经常要获取某个区间a[j]的最大值,所以用线段树维护。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <vector> 4 #include <algorithm> 5 using namespace std; 6 const int N=250000*2+5; 7 const int M= 1e9+7; 8 typedef long long ll; 9 struct node{ 10 int l,r; 11 ll Max,sum; 12 }tree[4*N]; 13 struct edge{ 14 int id; 15 int v; 16 bool operator <(const edge &x) const{ 17 return v<x.v; 18 } 19 }; 20 int n; 21 ll a[N]; 22 vector<edge>b; 23 void pushup(int i){ 24 tree[i].sum=(tree[2*i].sum+tree[2*i+1].sum)%M;//别忘了mod运算 25 tree[i].Max=max(tree[2*i].Max,tree[2*i+1].Max); 26 } 27 void build(int l,int r,int i){ 28 if(i>8*n) return ; 29 tree[i].l=l; 30 tree[i].r=r; 31 if(tree[i].l==tree[i].r) { 32 if(l>n){ 33 tree[i].sum=0; 34 tree[i].Max=0; 35 }else{ 36 tree[i].sum=a[l]; 37 tree[i].Max=a[l]-l;//MAX存的是a[j]-j; 38 } 39 return ; 40 } 41 int mid=(l+r)/2; 42 build(l,mid,2*i); 43 build(mid+1,r,2*i+1); 44 pushup(i);//回溯更新父节点 45 } 46 void update(ll v,int x,int i){ 47 if(tree[i].l==tree[i].r){ 48 tree[i].sum=v; 49 tree[i].Max=v-x; 50 return ; 51 } 52 int mid=(tree[i].l+tree[i].r)/2; 53 if(x<=mid) update(v,x,2*i); 54 else update(v,x,2*i+1); 55 pushup(i); 56 } 57 ll query(int l,int r,int i){ 58 if(tree[i].l==l && tree[i].r==r) return tree[i].Max; 59 int mid=(tree[i].l+tree[i].r)/2; 60 if(r<=mid) return query(l,r,2*i); 61 else if(l>mid) return query(l,r,2*i+1); 62 else if(l<=mid && r>mid) return max(query(l,mid,2*i),query(mid+1,r,2*i+1)); 63 } 64 int main(){ 65 while(scanf("%d",&n)!=EOF){ 66 int pre=0; 67 b.clear(); 68 for(int i=1;i<=n;i++){ 69 scanf("%I64d",&a[i]); 70 } 71 build(1,2*n,1); 72 for(int i=1;i<=n;i++){ 73 edge x; 74 scanf("%d",&x.v); 75 x.id=i; 76 b.push_back(x); 77 } 78 sort(b.begin(),b.end()); 79 for(int i=n+1;i<=2*n;i++){ 80 ll x,y; 81 int bg,ed=i-1; 82 x=bg=b[pre++].v;//排序完直接按顺序取b数组,保证了不会重复使用 83 y=query(bg,ed,1); 84 a[i]=max(x,y); 85 update(a[i],i,1); 86 } 87 printf("%I64d\n",tree[3].sum);//tree[3]保存的是n+1…2*n的节点信息 88 } 89 return 0; 90 }
HDU 6047 Maximum Sequence(贪心+线段树)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。