51nod 1672-区间交(线段树)

来源:互联网 发布:打水软件是什么 编辑:程序博客网 时间:2024/06/06 06:38
1672 区间交
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
 收藏
 关注
小A有一个含有n个非负整数的数列与m个区间,每个区间可以表示为li,ri。
它想选择其中k个区间, 使得这些区间的交的那些位置所对应的数的和最大。(是指k个区间共同的交,即每个区间都包含这一段,具体可以参照样例)

在样例中,5个位置对应的值分别为1,2,3,4,6,那么选择[2,5]与[4,5]两个区间的区间交为[4,5],它的值的和为10。
Input
第一行三个数n,k,m(1<=n<=100000,1<=k<=m<=100000)。接下来一行n个数ai,表示小A的数列(0<=ai<=10^9)。接下来m行,每行两个数li,ri,表示每个区间(1<=li<=ri<=n)。
Output
一行表示答案
Input示例
5 2 31 2 3 4 64 52 51 4
Output示例
10
Joe (题目提供者)
C++的运行时限为:1000 ms ,空间限制为:131072 KB 示例及语言说明请按这里

 允许其他 AC 的用户查看此代码,分享代码才能查看别人的代码并有机会获得勋章


刚开始想着二分搞搞,然后各种小细节和问题,debug了半天果断换方法,想着还是拿线段树搞搞吧,我们可以枚举区间,每遇到一个区间便把当前区间右端点加入线段树,这样我们就能枚举左端点来求解最大值了,当然,前k-1个左端点不用枚举。。。。

#include<map>       #include<stack>              #include<queue>              #include<vector>      #include<string>    #include<math.h>              #include<stdio.h>              #include<iostream>              #include<string.h>              #include<stdlib.h>      #include<algorithm>     #include<functional>      using namespace std;typedef long long  ll;#define inf  1000000000         #define mod 1000000007               #define maxn  886000    #define PI 3.1415926  #define lowbit(x) (x&-x)              #define eps 1e-9    ll sum[maxn], a[maxn], sm[maxn];struct node{ll l, r;}b[maxn];bool comp(node a, node b){if (a.l == b.l)return a.r < b.r;return a.l < b.l;}void update(ll id, ll l, ll r, ll x){if (l == r){sum[id]++;return;}ll mid = (l + r) / 2;if (mid >= x)update(id * 2, l, mid, x);elseupdate(id * 2 + 1, mid + 1, r, x);sum[id] = sum[id * 2] + sum[id * 2 + 1];} ll query(ll id, ll l, ll r, ll x)  {if (l == r)return l;ll mid = (l + r) / 2;if (sum[id * 2 + 1] >= x)return query(id * 2 + 1, mid + 1, r, x);elsereturn query(id * 2, l, mid, x-sum[id*2+1]);}int main(void){ll ans = 0;ll n, m, k, i, j;scanf("%lld%lld%lld", &n, &k, &m);for (i = 1;i <= n;i++){scanf("%lld", &a[i]);sm[i] = sm[i - 1] + a[i];}for (i = 1;i <= m;i++)scanf("%lld%lld", &b[i].l, &b[i].r);sort(b + 1, b + m + 1, comp);for (i = 1;i < k;i++)update(1, 1, n, b[i].r);for (i = k;i <= m;i++){update(1, 1, n, b[i].r);ll pos = query(1, 1, n, k);if (pos >= b[i].l)ans = max(ans, sm[pos] - sm[b[i].l - 1]);}printf("%lld\n", ans);return 0;}


原创粉丝点击