【多校训练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  }

线段树区间查询最优值+单点修改

时间: 2024-12-25 17:11:51

【多校训练2】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 o

hdu 6047 Maximum Sequence(贪心)

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 c

HDU 6047 Maximum Sequence (贪心+单调队列)

题意:给定一个序列,让你构造出一个序列,满足条件,且最大.条件是 选取一个ai <= max{a[b[j], j]-j} 析:贪心,贪心策略就是先尽量产生大的,所以就是对于B序列尽量从头开始,由于数据比较大,采用桶排序,然后维护一个单调队列,使得最头上最大. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #i

【链表】2017多校训练3 HDU 6058 Kanade&#39;s sum

acm.hdu.edu.cn/showproblem.php?pid=6058 [题意] 给定一个排列,计算 [思路] 计算排列A中每个数的贡献,即对于每个ai,计算有ni个区间满足ai是区间中的第k大,那么ai对答案的贡献就是ai*ni 以ai为起点,统计ai右边离ai最近的,比ai大的k个数的位置 同理统计左边的位置,组合得到答案 关键是得到比ai大的离ai最近的k个数的位置 因为是排列,所以每个数都不相等,可以记录每个数的位置,然后从小到大枚举ai,这样维护一个双向链表,保证链表中的数就是

【极角排序+双指针线性扫】2017多校训练七 HDU 6127 Hard challenge

acm.hdu.edu.cn/showproblem.php?pid=6127 [题意] 给定平面直角坐标系中的n个点,这n个点每个点都有一个点权 这n个点两两可以连乘一条线段,定义每条线段的权值为线段两端点点权的乘积 现在要过原点作一条直线,要求这条直线不经过任意一个给定的点 在所有n个点两两连成的线段中,计算与这条直线有交点的线段的权值和 最大化这个权值和并输出 题目保证,给定的n个点不重合且任意两个点的连线不经过原点 [思路] 一条经过原点的直线把n个点分成两个半平面A,B 假设A中的点权

【组合数+Lucas定理】2017多校训练七 HDU 6129 Just do it

http://acm.hdu.edu.cn/showproblem.php?pid=6129 [题意] 对于一个长度为n的序列a,我们可以计算b[i]=a1^a2^......^ai,这样得到序列b 重复这样的操作m次,每次都是从上次求出的序列a得到一个新序列b 给定初始的序列,求重复m次操作后得到的序列 [思路] 假定n=5,我们模拟一次可以发现,经过m次操作后a1在b1......bn中出现的次数为: m=0: 1 0 0 0 0 m=2: 1 2 3 4 5 m=3: 1 3 6 10 1

【双向bfs】2017多校训练十 HDU 6171 Admiral

[题意] 现在给出一个三角矩阵,如果0编号的在点(x,y)的话,可以和(x+1,y),(x-1,y),(x+1,y+1),(x-1,y-1)这些点进行交换. 我们每一次只能对0点和其他点进行交换.问最少步数,使得最终变成: 0 1 1 2 2 2 3 3 3 3 4 4 4 4 4 5 5 5 5 5 5 [思路] [AC] 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef un

hdu 4915 Parenthese sequence(模拟)2014多校训练第5场

Parenthese sequence                                                                     Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description bobo found an ancient string. The string contains only t

多校训练hdu --Nice boat(线段树,都是泪)

Nice boat Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 47 Accepted Submission(s): 10 Problem Description There is an old country and the king fell in love with a devil. The devil always ask