【多校训练2】HDU 6047 Maximum Sequence

http://acm.hdu.edu.cn/showproblem.php?pid=6047

【题意】

  • 给定两个长度为n的序列a和b,现在要通过一定的规则找到可行的a_n+1.....a_2n,求sum{a_n+1.....a_2n}的最大值
  • 每次从序列b中选择一个数bk,那么构造的ai就是max{aj -j},其中bk<=j<i
  • 每个bk最多用一次

【思路】

  • 首先我们需要的是aj-j
  • 可以贪心,即对于当前要构造的数ai,尽可能找bk使得能够取得最大的aj-j
  • 线段树区间查询最优值+单点更新
  • 把b排个序,对于每个b查询b[i]~n+i-1的最大值

【Accepted】

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<algorithm>
  6 #include<cmath>
  7 #define lson (i<<1)
  8 #define rson (i<<1|1)
  9 #include<vector>
 10 #include<map>
 11 using namespace std;
 12 const int maxn=(25e4+5)*2;
 13 typedef long long ll;
 14 const ll mod=1e9+7;
 15 const int inf=0x3f3f3f3f;
 16 long long val[maxn];
 17 int a[maxn];
 18 int b[maxn];
 19 int n;
 20 struct Seg
 21 {
 22     int l,r,lazy,val;
 23 }tree[maxn<<2];
 24 
 25 void push_up(int i)
 26 {
 27     tree[i].val=max(tree[lson].val,tree[rson].val);
 28 }
 29 
 30 void push_down(int i)
 31 {
 32     if(tree[i].lazy==-1)
 33     {
 34         return;
 35     }
 36     tree[lson].lazy=tree[lson].val=tree[i].lazy;
 37     tree[rson].lazy=tree[rson].val=tree[i].lazy;
 38     tree[i].lazy=-1;
 39 }
 40 
 41 void Build(int l,int r,long long i=1)
 42 {
 43     tree[i].l=l;
 44     tree[i].r=r;
 45     tree[i].lazy=-1;
 46     if(l==r)
 47     {
 48         tree[i].val=val[l];
 49         return;
 50     }
 51     push_down(i);
 52     int mid=(tree[i].l+tree[i].r)>>1;
 53     Build(l,mid,lson);
 54     Build(mid+1,r,rson);
 55     push_up(i);
 56 }
 57 
 58 int Query(int l,int r,int i=1)
 59 {
 60     if(tree[i].l==l&&tree[i].r==r)
 61     {
 62         return tree[i].val;
 63     }
 64     push_down(i);
 65     int mid=(tree[i].l+tree[i].r)>>1;
 66     if(r<=mid)
 67     {
 68         return Query(l,r,lson);
 69     }
 70     else if(l>mid)
 71     {
 72         return Query(l,r,rson);
 73     }
 74     else
 75     {
 76         return max(Query(l,mid,lson),Query(mid+1,r,rson));
 77     }
 78 }
 79 
 80 void Setval(int l,int r,int x,int i=1)
 81 {
 82     if(tree[i].l==l&&tree[i].r==r)
 83     {
 84         tree[i].lazy=tree[i].val=x;
 85         return;
 86     }
 87     push_down(i);
 88     int mid=(tree[i].l+tree[i].r)>>1;
 89     if(r<=mid)
 90     {
 91         Setval(l,r,x,lson);
 92     }
 93     else if(l>mid)
 94     {
 95         Setval(l,r,x,rson);
 96     }
 97     else
 98     {
 99         Setval(l,mid,x,lson);
100         Setval(mid+1,r,x,rson);
101     }
102     push_up(i);
103  }
104 
105 int main()
106 {
107     while(~scanf("%d",&n))
108     {
109         for(int i=1;i<=2*n;i++)
110         {
111             val[i]=-inf;
112         }
113         for(int i=1;i<=n;i++)
114         {
115             scanf("%d",&a[i]);
116             val[i]=a[i]-i;
117         }
118         Build(1,2*n);
119         for(int i=1;i<=n;i++)
120         {
121             scanf("%d",&b[i]);
122         }
123         sort(b+1,b+1+n);
124         ll ans=0;
125         b[0]=0;
126         for(int i=1;i<=n;i++)
127         {
128             int mmax=Query(b[i],n+i-1);
129             ans=(ans+(ll)mmax)%mod;
130             Setval(n+i,n+i,mmax-(n+i));
131         }
132         cout<<ans<<endl;
133     }
134     return 0;
135  }
线段树区间查询最优值+单点修改
原文地址:https://www.cnblogs.com/itcsl/p/7253039.html