【Foreign】Melancholy [线段树]
Melancholy
Time Limit: 10 Sec Memory Limit: 256 MB
Description
DX3906星系,Melancholy星上,我在勘测这里的地质情况。
我把这些天来已探测到的区域分为N组,并用二元组(D,V)对每一组进行标记:其中D为区域的相对距离,V为内部地质元素的相对丰富程度
在我的日程安排表上有Q项指派的计划。
每项计划的形式是类似的,都是“对相对距离D在[L,R]之间的区域进行进一步的勘测,并在其中有次序地挑出K块区域的样本进行研究。”采集这K块的样品 后,接下来在实验中,它们的研究价值即为这K块区域地质相对丰富程度V的乘积。
我对这Q项计划都进行了评估:一项计划的评估值P为所有可能选取情况的研究价值之和。
但是由于仪器的原因,在一次勘测中,这其中V最小的区域永远不会被选取。
现在我只想知道这Q项计划的评估值对2^32取模后的值,特殊地,如果没有K块区域可供选择, 评估值为0。
Input
第一行给出两个整数,区域数N与计划数Q。
第二行给出N个整数,代表每一块区域的相对距离D。
第三行给出N个整数,代表每一块区域的内部地质元素的相对丰富程度V。
接下来的Q行,每一行3个整数,代表相对距离的限制L,R,以及选取的块数K。
Output
输出包括Q行,每一行一个整数,代表这项计划的评估值对2^32取模后的值。
Sample Input
5 3
5 4 7 2 6
1 4 5 3 2
6 7 1
2 6 2
1 8 3
Sample Output
5
52
924

HINT

Main idea
查询D在[L, R]中的元素,去掉最小的L值之后,任意k几个相乘的和。
Solution
首先,我们可以按照D排序一下,然后调出D在[L,R]的元素,显然是连续的一段。
然后我们再记录一下最小值L,以及最小值L所在的位置。这样在线段树上区间查询一下,就可以得到最小值的pos。
那么我们就将询问化成了,查询两个区间的信息并且合并。
问题在于如何合并。
我们对于线段树上的每个节点,记录一下val[i]表示选了i个乘起来的和。
那么两个区间合并起来时,val[i] = ΣA.val[j] * B.val[i - j],根据乘法分配律可以看出。
比如我们左区间选了2个的答案形如:x1·x2 + y1·y2,右区间选了1个的答案形如:z1 + z2。
那么合并之后的区间 选了3个答案形如:x1·x2·z1 + x1·x2·z2 + y1·y2·z2+ y1·y2·z2,显然就是两个乘起来,并且不漏状态。
这样就可以得到答案啦。
Code
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef unsigned int u32; const int ONE = ;
const int MOD = 1e9 + ;
const u32 INF = 4294967295u; int n, Q;
int k;
struct point
{
u32 d, v;
}a[ONE], L, R;
bool cmp(const point &a, const point &b) {return a.d < b.d;} struct power
{
u32 val[];
friend power operator +(power a, power b)
{
power c;
for(int i = ; i <= ; i++) c.val[i] = a.val[i] + b.val[i];
for(int i = ; i <= ; i++)
for(int j = ; j < i; j++)
c.val[i] += a.val[j] * b.val[i - j];
return c;
}
}Node[ONE], A[], Ans; struct Min
{
u32 val, pos;
friend Min operator +(Min a, Min b)
{
Min c = (Min){INF, };
if(a.val < c.val) c = a;
if(b.val < c.val) c = b;
return c;
}
}Val[ONE], res_min; int get()
{
int res=,Q=; char c;
while( (c=getchar())< || c>)
if(c=='-')Q=-;
if(Q) res=c-;
while((c=getchar())>= && c<=)
res=res*+c-;
return res*Q;
} namespace Seg
{
void Build(int i, int l, int r)
{
Val[i] = (Min){INF, };
for(int j = ; j <= ; j++) Node[i].val[j] = ;
if(l == r)
{
Node[i].val[] = a[l].v;
Val[i] = (Min){a[l].v, l};
return;
}
int mid = l + r >> ;
Build(i << , l, mid); Build(i << | , mid + , r);
Node[i] = Node[i << ] + Node[i << | ];
Val[i] = Val[i << ] + Val[i << | ];
} void Find(int i, int l, int r, int L, int R)
{
if(L > R) return;
if(L <= l && r <= R)
{
res_min = res_min + Val[i];
return;
}
int mid = l + r >> ;
if(L <= mid) Find(i << , l, mid, L, R);
if(mid + <= R) Find(i << | , mid + , r, L, R);
} void Query(int i, int l, int r, int L, int R, int opt)
{
if(L > R) return;
if(L <= l && r <= R)
{
A[opt] = A[opt] + Node[i];
return;
}
int mid = l + r >> ;
if(L <= mid) Query(i << , l, mid, L, R, opt);
if(mid + <= R) Query(i << | , mid + , r, L, R, opt);
}
} void Deal(int k)
{
int Left = lower_bound(a + , a + n + , L, cmp) - a;
int Right = upper_bound(a + , a + n + , R, cmp) - a - ;
if(Left >= Right) {printf("0\n"); return;} res_min = (Min){INF, };
Seg::Find(, , n, Left, Right); for(int i = ; i <= ; i++) A[].val[i] = A[].val[i] = ;
Seg::Query(, , n, Left, res_min.pos - , );
Seg::Query(, , n, res_min.pos + , Right, ); Ans = A[] + A[];
for(u32 i = ; i <= k; i++) Ans.val[k] *= i;
printf("%u\n", Ans.val[k]);
} int main()
{
n = get(); Q = get();
for(int i = ; i <= n; i++) a[i].d = get();
for(int i = ; i <= n; i++) a[i].v = get();
sort(a + , a + n + , cmp); Seg::Build(, , n); while(Q--)
{
L.d = get(), R.d = get(), k = get();
Deal(k);
}
}
【Foreign】Melancholy [线段树]的更多相关文章
- 【Foreign】数据结构C [线段树]
数据结构C Time Limit: 20 Sec Memory Limit: 512 MB Description Input Output Sample Input Sample Output H ...
- 【Foreign】Weed [线段树]
Weed Time Limit: 20 Sec Memory Limit: 512 MB Description 从前有个栈,一开始是空的. 你写下了 m 个操作,每个操作形如 k v : 若 k ...
- 【Foreign】划分序列 [线段树][DP]
划分序列 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output 仅一行一个整数表示答案. Sample Input 9 4 ...
- 【Foreign】染色 [LCT][线段树]
染色 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output Sample Input 13 0 1 0 2 1 11 1 ...
- 【Foreign】阅读 [线段树][DP]
阅读 Time Limit: 10 Sec Memory Limit: 256 MB Description Input Output Sample Input 0 10 4 10 2 3 10 8 ...
- bzoj3932--可持久化线段树
题目大意: 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第 ...
- codevs 1082 线段树练习 3(区间维护)
codevs 1082 线段树练习 3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 大师 Master 题目描述 Description 给你N个数,有两种操作: 1:给区 ...
- codevs 1576 最长上升子序列的线段树优化
题目:codevs 1576 最长严格上升子序列 链接:http://codevs.cn/problem/1576/ 优化的地方是 1到i-1 中最大的 f[j]值,并且A[j]<A[i] .根 ...
- codevs 1080 线段树点修改
先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...
随机推荐
- lintcode-206-区间求和 I
206-区间求和 I 给定一个整数数组(下标由 0 到 n-1,其中 n 表示数组的规模),以及一个查询列表.每一个查询列表有两个整数 [start, end] . 对于每个查询,计算出数组中从下标 ...
- Apache Hadoop YARN – NodeManager--转载
原文地址:http://zh.hortonworks.com/blog/apache-hadoop-yarn-nodemanager/ The NodeManager (NM) is YARN’s p ...
- 【bzoj3119】Book 数学
题目描述 一个长度为N的序列的首项为X,以后的每一项要么比前一项大A,要么比前一项小B.已知总和为M,求一组可行方案. 输入 第一行一个正整数N.第二行四个整数依次是X,A,B,M. 输出 输出一行N ...
- [十六]SpringBoot 之 读取环境变量和绑定属性对象
1.读取环境变量 凡是被spring管理的类,实现接口EnvironmentAware 重写方法 setEnvironment 可以在工程启动时,获取到系统环境变量和application配置文件中的 ...
- Django模板语言循环字典
1. 对于字典,可以有下列用法: {% for row in user_dict.keys %} {% for row in user_dict.values %} {% for row in use ...
- ssh后台执行
1 执行scp命令,开始传输2 scp传输开始后,用ctrl+z,再以bg命令将其转入后台运行. 3以exit命令安全退出即可令scp继续执行,不受关闭shell的影响.
- Codeforces 906B. Seating of Students(构造+DFS)
行和列>4的可以直接构造,只要交叉着放就好了,比如1 3 5 2 4和2 4 1 3 5,每一行和下一行用不同的方法就能保证没有邻居. 其他的可以用爆搜,每次暴力和后面的一个编号交换并判断可行性 ...
- 解题:POI 2016 Nim z utrudnieniem
题面 出现了,神仙题! 了解一点博弈论的话可以很容易转化题面:问$B$有多少种取(diu)石子的方式使得取后剩余石子异或值为零且取出的石子堆数是$d$的倍数 首先有个暴力做法:$dp[i][j][k] ...
- 【agc017E】Jigsaw
Portal -->agc017 Description 给你\(n\)块积木,每块积木由三个矩形组成,中间的矩形最高高度为\(h\),左边的矩形高度为\(a_i\)离底边高度为\(c_i\), ...
- 最近公共祖先(LCA)(题目)
Time Limit: 2000 ms Memory Limit: 256 MB Description Input Output Sample Input 15 5 1 2 3 4 5 6 7 8 ...