【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 线段树点修改
先来介绍一下线段树. 线段树是一个把线段,或者说一个区间储存在二叉树中.如图所示的就是一棵线段树,它维护一个区间的和. 蓝色数字的是线段树的节点在数组中的位置,它表示的区间已经在图上标出,它的值就是这 ...
随机推荐
- iOS界面设计之基础控件的学习 --- UITextField
学习iOS界面设计也有段时间了,每次写到一些基础控件(如:UILable . UITextField)的时候就深觉应该总结一个函数来实现这些基础控件的属性设置,所以下面就是我对UITextField的 ...
- 条形码生成库 BarcodeLib
官方介绍 在ASP.NET,Windows,Reporting Service,Crystal Reports 和 RDLC Reports应用程序中轻松生成条形码 生成准确的条形码图像,并可以保存为 ...
- 编写shell时,遇到let: not found错误及解决办法
#!/bin/bashi=1sum=0while [ $i -le 100 ]do let sum=sum+$i let i++ done 在写一个简单的循环脚本时,报错 let: not fou ...
- Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错,
Linux下编译程序时,经常会遇到“undefined reference to XXX” 报错, 这里总结一些可能的原因和解决方案,给需要的朋友: 说道undefined reference err ...
- hdu-题目1159:Common Subsequence
http://acm.hdu.edu.cn/showproblem.php?pid=1159 Common Subsequence Time Limit: 2000/1000 MS (Java/Oth ...
- Spring注解原理
一.注解的基本概念和原理及其简单实用 注解(Annotation)提供了一种安全的类似注释的机制,为我们在代码中添加信息提供了一种形式化得方法,使我们可以在稍后某个时刻方便的使用这些数据(通过解析注解 ...
- FZU2127_养鸡场
题目的意思为要你求出满足三边范围条件且周长为n的三角形的数目. 其实做法是直接枚举最短边,然后就可以知道第二条边的取值范围,同时根据给定的范围缩小范围. 同时根据第二条边的范围推出第三条边的范围,再次 ...
- java finally 与return
finally之外的语句块有return,finally语句块没有return:该语句块的返回值被固定下来,等fianlly执行完后返回给调用者 finally语句块与其他语句块同时有return:返 ...
- 秒杀多线程第二篇 多线程第一次亲密接触 CreateThread与_beginthreadex本质区别(续)
由于原作者主要写window上的线程,而我主要学习android,所以本文将分析android方面多线程. 1.Thread: public void Thread1(){ Thread a = ne ...
- [四]SpringBoot 之 捕捉全局异常
在class注解上@ControllerAdvice, 在方法上注解上@ExceptionHandler(value = Exception.class),具体代码如下: package me.shi ...