【Hihocoder1034】毁灭者问题(splay,树状数组)
题意:
假设你拥有 n 个魔法单位,他们从左到有站在一行,编号从 1 到 n。 每个单位拥有三项属性:
si: 初始法力。
mi: 最大法力上限。
ri: 每秒中法力回复速度。
现在你操纵一个毁灭者,有 m 个操作,t l r,表示时刻 t,毁灭者对所有编号从 l 到 r 的单位,使用了魔法吸收。操作按照时间顺序给出,计算毁灭者一共吸收了多少法力。
n<=10^5 s[i],m[i],r[i]<=10^5 m<=10^5 maxtime<=10^9
思路:RYZ作业
因为每个人的回复速度不同且都有上限,所以不能用线段树完成
转换思路,不能维护每个人的魔法值,就应该维护时间点与时间间隔
考虑单位i,假设它回满的时间长为man,那么它对答案的贡献就是s1*r[i]+s2*m[i]
其中s1为<man的间隔的总和,s2为>=man的间隔的个数
现在问题转化成:
时间间隔需要维护插入,删除,子树大小和子树和,平衡树即可
时间点需要维护前驱,后继,插入,删除,我用树状数组,每次操作O(log^2 n),如果用平衡树可以达到O(log n)
需要注意的是查询[0,man-1]这段区间时需要找到第一个>man-1的位置,而查询[man,oo]这段时需要找到最后一个<man的位置,所以rank函数不能共用
总复杂度O(m log^2 n),维护时间时使用平衡树可以达到O(m log n)
不过m,n只有100000,煮不在糊
话说这个OJ不能用P交,那只能用对拍了
var t:array[..,..]of longint;
size,fa,l1,l2,l3,r1,r2,r3,
x,y,z,c,time,t1,t2,t3,s,m,r,q:array[..]of longint;
sum,num:array[..]of int64;
n,i,que,head,tail,up,k,tot,root,cnt,k1,k2,man,kk,tmp,j:longint;
ans1,ans2,s1,s2:int64;
flag:boolean; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; procedure pushup(x:longint);
var l,r:longint;
begin
l:=t[x,]; r:=t[x,];
size[x]:=size[l]+size[r]+;
// size[x]:=size[l]+size[r];
sum[x]:=sum[l]+sum[r];
if (num[x]<>maxlongint)and(num[x]<>-) then sum[x]:=sum[x]+num[x];
end; procedure rotate(x:longint;var k:longint);
var y,z,l,r:longint;
begin
y:=fa[x]; z:=fa[y];
if t[y,]=x then l:=
else l:=;
r:=l xor ;
if y<>k then
begin
if t[z,]=y then t[z,]:=x
else t[z,]:=x;
end
else k:=x;
fa[x]:=z; fa[y]:=x; fa[t[x,r]]:=y;
t[y,l]:=t[x,r]; t[x,r]:=y;
pushup(y);
pushup(x);
end; procedure splay(x:longint;var k:longint);
var y,z:longint;
begin
while x<>k do
begin
y:=fa[x]; z:=fa[y];
if y<>k then
begin
if (t[y,]=x)xor(t[z,]=y) then rotate(x,k)
else rotate(y,k);
end
else k:=x;
rotate(x,k);
end;
end; function kth(x:longint):longint;
var k,tmp:longint;
begin
k:=root;
while true do
begin
tmp:=size[t[k,]]+;
if tmp=x then exit(k);
if tmp>x then k:=t[k,]
else
begin
k:=t[k,]; x:=x-tmp;
end;
end;
end; function pred(x:longint):longint;
var k,last:longint;
begin
k:=root; last:=num[root];
while k<> do
begin
if num[k]<x then begin last:=num[k]; k:=t[k,]; end
else k:=t[k,];
end;
exit(last);
end; function succ(x:longint):longint;
var k,last:longint;
begin
k:=root; last:=maxlongint;
while k<> do
begin
if num[k]>x then begin last:=num[k]; k:=t[k,]; end
else k:=t[k,];
end;
exit(last);
end; function rank(x:longint):longint;
var k:longint;
begin
if x=- then exit();
x:=pred(x);
k:=root; rank:=;
while k> do
begin
if num[k]<=x then begin rank:=rank+size[t[k,]]+; k:=t[k,]; end
else k:=t[k,];
end;
inc(rank);
end; procedure ins(x:longint);
var k,l,r:longint;
begin
if x= then exit;
// if x< then begin writeln('error ',i); exit; end;
k:=rank(x);
l:=kth(k-);
r:=kth(k);
splay(l,root);
splay(r,t[root,]);
k:=t[root,];
inc(cnt); t[k,]:=cnt; fa[cnt]:=k;
size[cnt]:=; num[cnt]:=x; sum[cnt]:=x;
inc(tot);
// writeln('ins ',x,' ',tot);
end; procedure del(x:longint);
var k,l,r,k1,k2:longint;
begin
if x= then exit;
k:=rank(x);
l:=kth(k-);
r:=kth(k+);
splay(l,root);
splay(r,t[root,]);
k1:=t[root,]; k2:=t[k1,];
size[k1]:=size[t[k1,]]+;
//sum[k1]:=sum[t[k1,]]+num[k1];
sum[k1]:=sum[t[k1,]];
if (num[k1]<>maxlongint)and(num[k1]<>-) then sum[k1]:=sum[k1]+num[k1];
fa[k2]:=; sum[k2]:=; size[k2]:=;
t[k2,]:=; t[k2,]:=; num[k2]:=;
t[k1,]:=;
dec(tot);
//writeln('del ',x,' ',tot);
end; function lowbit(x:longint):longint;
begin
exit(x and (-x));
end; function sumbit(x:longint):longint;
begin
sumbit:=;
while x> do
begin
sumbit:=sumbit+q[x];
x:=x-lowbit(x);
end;
end; procedure add(x,s:longint);
begin
while x<= do
begin
q[x]:=q[x]+s;
x:=x+lowbit(x);
end;
end; procedure qsort1(l,r:longint);
var mid,i,j:longint;
begin
i:=l; j:=r; mid:=l1[(l+r)>>];
repeat
while mid>l1[i] do inc(i);
while mid<l1[j] do dec(j);
if i<=j then
begin
swap(l1[i],l1[j]);
swap(r1[i],r1[j]);
swap(t1[i],t1[j]);
inc(i); dec(j);
end;
until i>j;
if l<j then qsort1(l,j);
if i<r then qsort1(i,r);
end; procedure qsort2(l,r:longint);
var mid,i,j:longint;
begin
i:=l; j:=r; mid:=r2[(l+r)>>];
repeat
while mid>r2[i] do inc(i);
while mid<r2[j] do dec(j);
if i<=j then
begin
swap(l2[i],l2[j]);
swap(r2[i],r2[j]);
swap(t2[i],t2[j]);
inc(i); dec(j);
end;
until i>j;
if l<j then qsort2(l,j);
if i<r then qsort2(i,r);
end; function findkth(x:longint):longint;
var l,r,mid,last,tmp:longint;
begin
l:=; r:=; last:=;
while l<=r do
begin
mid:=(l+r)>>;
tmp:=sumbit(mid);
{if tmp<=x then begin last:=mid; l:=mid+1; end
//else r:=mid-1; }
if tmp>x then r:=mid-
else if tmp<x then begin last:=mid; l:=mid+ end
else if tmp=x then begin last:=mid; r:=mid-; end; end;
if sumbit(last)<x then inc(last);
exit(last);
end; {function findkth(x:longint):longint;
var ret,p:longint;
begin
p:=1<<17; ret:=0;
while p>0 do
begin
if q[ret+p]<=x then
begin
ret:=ret+p;
x:=x-q[ret];
end;
p:=p>>1;
end;
exit(ret);
end; } function hash(x:longint):longint;
var l,r,mid,last:longint;
begin
l:=; r:=up; last:=;
while l<=r do
begin
mid:=(l+r)>>;
if time[mid]=x then exit(mid)
else if time[mid]>x then r:=mid-
else l:=mid+;
end;
//exit(last);
end; function querymn(x:longint):int64;
var k1,k2:longint;
begin
k1:=kth();
k2:=kth(rank(succ(x-)));
splay(k1,root);
splay(k2,t[root,]);
exit(sum[t[k2,]]);
// exit(size[t[k2,]]);
end; function querymx(x:longint):int64;
var k1,k2,s:longint;
begin
k1:=pred(x);
k:=root; s:=;
while k> do
begin
if num[k]<=k1 then begin s:=s+size[t[k,]]+; k:=t[k,]; end
else k:=t[k,];
end; k1:=kth(s);
k2:=kth(tot);
splay(k1,root);
splay(k2,t[root,]);
exit(size[t[k2,]]);
end; function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; begin
assign(input,'data.in'); reset(input);
assign(output,'hihocoder1034.out'); rewrite(output);
readln(n);
for i:= to n do read(s[i],m[i],r[i]);
readln(que);
for i:= to que do
begin
read(x[i],y[i],z[i]);
inc(x[i]);
end;
l1:=y; r1:=z; t1:=x;
l2:=y; r2:=z; t2:=x;
l3:=y; r3:=z; t3:=x;
qsort1(,que);
qsort2(,que); if time[]= then begin time[]:=; up:=; end
else begin time[]:=; time[]:=t3[]; up:=; end;
for i:= to que do
if t3[i]<>time[up] then begin inc(up); time[up]:=t3[i]; end;
inc(up); time[up]:=maxlongint;
add(,);
add(,);
num[]:=maxlongint; size[]:=;
t[,]:=;
num[]:=-; fa[]:=; size[]:=;
root:=; cnt:=; tot:=;
//for i:= to que do c[i]:=hash(x[i]);
head:=; tail:=; for i:= to n do
begin if r[i]= then man:=maxlongint-
else
begin
if m[i] mod r[i]= then man:=m[i] div r[i]
else man:=m[i] div r[i]+;
end; while (head<=que)and(i>=l1[head]) do
begin
kk:=hash(t1[head]);
k:=sumbit(kk-)+;
k1:=findkth(k-);
k2:=findkth(k);
ins(t1[head]-time[k1]);
if k2<> then ins(time[k2]-t1[head]);
if k2<> then del(time[k2]-time[k1]);
add(kk,); inc(head);
end; while (tail<=que)and(i>r2[tail]) do
begin
kk:=hash(t2[tail]);
k:=sumbit(kk-)+;
k1:=findkth(k-);
k2:=findkth(k+);
if k2<> then ins(time[k2]-time[k1]);
del(t2[tail]-time[k1]);
if k2<> then del(time[k2]-t2[tail]);
add(kk,-); inc(tail);
end; s1:=querymn(man);
s2:=querymx(man);
ans1:=ans1+s1*r[i]+s2*m[i]; { s1:=0;
for j:=1 to cnt do
if (num[j]<>0)and(num[j]<man) then inc(s1);
s2:=0;
for j:=1 to cnt do
if (num[j]<>0)and(num[j]>=man) then inc(s2); ans2:=ans2+s1*r[i]+s2*m[i]; }
k:=findkth();
if k<> then
begin
tmp:=time[k];
s1:=tmp-;
s1:=s1*r[i];
if m[i]<s1 then s1:=m[i]; //start with
s2:=tmp-;
s2:=s2*r[i]+s[i];
if m[i]<s2 then s2:=m[i]; //start with s[i]
ans1:=ans1-s1+s2;
end;
// writeln(ans1);
//writeln(ans2); end; writeln(ans1); close(input);
close(output);
end.
【Hihocoder1034】毁灭者问题(splay,树状数组)的更多相关文章
- NOIP 2017 列队 - Splay - 树状数组
题目传送门 传送点I 传送点II 题目大意 (家喻户晓的题目应该不需要大意) (我之前咋把NOIP 2017打成了NOIP 2018,好绝望) Solution 1 Splay 每行一颗Splay,没 ...
- HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436 树状数组做法<猛戳> Splay tree的经典题目,有删除和移动操作.首先要离散化 ...
- HDU 3436--Queue-jumpers (树状数组 or Splay Tree)
树状数组这个真心想了好久,还是没想出来 %%% www.cppblog.com/Yuan/archive/2010/08/18/123871.html 树状数组求前缀和大于等于k的最大值,第一次看到这 ...
- 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay
正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...
- 白白的(baibaide)——树状数组套主席树+splay
题目 [题目描述] 有一个长度为 $n$ 的序列 $a_1, a_2, \dots, a_n$,一开始每个位置都是白色.如果一个区间中每个位置都是白色,则称这是一个白白的区间.如果一个白白的区间向左或 ...
- POJ3468:A Simple Problem with Integers (线段树||树状数组||Splay解决基本问题的效率对比)
You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of op ...
- BZOJ_1901_&_ZJU_2112_Dynamic_Rankings_(主席树+树状数组/线段树+(Treap/Splay))
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1901 给出一个长度为n的数列A,有m次询问,询问分两种:1.修改某一位置的值;2.求区间[l, ...
- 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治
3648: 寝室管理 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 239 Solved: 106[Submit][Status][Discuss] ...
- 【BZOJ】1878: [SDOI2009]HH的项链(树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=1878 我太弱了,看题解才过的. 一开始看到此题,我想了想在线做法,但之后觉得这个想法可能是错的:维护 ...
随机推荐
- 如何启动Intel VT-x
如何启动Intel VT-x 5 在64bit win7系统下安装了Vmware10,然后安装64位的UbuntuKylin 14.04,想要打开UbuntuKylin,弹出如下对话框: 请问该如何启 ...
- SQL——SQL语言全部关键字详解
http://blog.csdn.net/quinnnorris/article/details/71056445 数据库中我们做常用的就是SQL基本查询语言,甚至有些人认为数据库就是SQL,SQL就 ...
- Html5怎么导出图片
其实很简单, 首先需要两个js文件 jquery.min.js html2canvas.js 直接上代码,几行就解决了 <a id="example1" onclick=&q ...
- C++ static关键字
一.面向过程中的static 1.修饰全局变量(静态全局变量) (1)静态全局变量在全局数据区分配内存: (2)未经初始化的静态全局变量会被程序自动初始化为0: (3)静态全局变量在申明它的整个文件是 ...
- objdump命令
0x00 objdump命令是Linux下的反汇编目标文件或者可执行文件的命令 0x01 objdump -f 显示test的文件头信息 $ objdump -f levellevel: file ...
- vuex其实超简单,只需3步
前言 之前几个项目中,都多多少少碰到一些组件之间需要通信的地方,而因为种种原因,event bus 的成本反而比vuex还高, 所以技术选型上选用了 vuex, 但是不知道为什么,团队里的一些新人一听 ...
- 【css】修改placeholder 默认颜色
html5为input添加了原生的占位符属性placeholder,高级浏览器都支持这个属性,例如: <input type="text" placeholder=" ...
- Java中File类的使用介绍
1.创建File对象的几种方式 import java.io.File; public class MyFile { public static void main(String[] args) { ...
- UVa 11987 并查集 Almost Union-Find
原文戳这 与以往的并查集不同,这次需要一个删除操作.如果是叶子节点还好,直接修改父亲指针就好. 但是如果要是移动根节点,指向它的所有子节点也会跟着变化. 所以要增加一个永远不会被修改的虚拟根节点,这样 ...
- VisionPro显示隐藏搜索区域
假如我们需要显示两张图,一张显示CogPMAlignTool工具不带搜索区域的,一张显示CogPMAlignTool工具带搜索区域的图像 VisionPro显示隐藏搜索区域 VisionPro显示隐藏 ...