1. 程式人生 > >HDU 6047 Maximum Sequence(貪心+線段樹)

HDU 6047 Maximum Sequence(貪心+線段樹)

cas nbsp like upd sca ring itl 當前 rem

題目網址: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+1a2n
. Just like always, there are some restrictions on an+1a2n: 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.

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(貪心+線段樹)