题意:

假设你拥有 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,树状数组)的更多相关文章

  1. NOIP 2017 列队 - Splay - 树状数组

    题目传送门 传送点I 传送点II 题目大意 (家喻户晓的题目应该不需要大意) (我之前咋把NOIP 2017打成了NOIP 2018,好绝望) Solution 1 Splay 每行一颗Splay,没 ...

  2. HDU-3436 Queue-jumpers 树状数组 | Splay tree删除,移动

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3436 树状数组做法<猛戳> Splay tree的经典题目,有删除和移动操作.首先要离散化 ...

  3. HDU 3436--Queue-jumpers (树状数组 or Splay Tree)

    树状数组这个真心想了好久,还是没想出来 %%% www.cppblog.com/Yuan/archive/2010/08/18/123871.html 树状数组求前缀和大于等于k的最大值,第一次看到这 ...

  4. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

  5. 白白的(baibaide)——树状数组套主席树+splay

    题目 [题目描述] 有一个长度为 $n$ 的序列 $a_1, a_2, \dots, a_n$,一开始每个位置都是白色.如果一个区间中每个位置都是白色,则称这是一个白白的区间.如果一个白白的区间向左或 ...

  6. 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 ...

  7. BZOJ_1901_&_ZJU_2112_Dynamic_Rankings_(主席树+树状数组/线段树+(Treap/Splay))

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1901 给出一个长度为n的数列A,有m次询问,询问分两种:1.修改某一位置的值;2.求区间[l, ...

  8. 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 239  Solved: 106[Submit][Status][Discuss] ...

  9. 【BZOJ】1878: [SDOI2009]HH的项链(树状数组)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1878 我太弱了,看题解才过的. 一开始看到此题,我想了想在线做法,但之后觉得这个想法可能是错的:维护 ...

随机推荐

  1. C#入门(3)

    C#入门(3) Delegates, Events, Lambda Expressions 最早的windows是使用c风格的函数指针来进行callback的,但是这样仅仅传递了一个内存中的地址,无法 ...

  2. 分享一个C++与Python开发的中小型通用游戏服务端框架(跨平台,开源,适合MMORPG游戏)

    在开发一款游戏项目时,在立项时我们往往会考虑或者纠结很多,比如: 1,对于开发来说:服务端和客户端应该选择什么语言?用什么协议通信才更效率?协议后期如何维护?Socket是用长连接还是短连接?TCP还 ...

  3. 【数论】贝壳找房计数比赛&&祭facinv

    震惊!阶乘逆元处理背后竟有如此玄机…… 题目描述 贝壳找房举办了一场计数比赛,比赛题目如下. 给一个字符串 s 和字符串 t,求出 s 的所有去重全排列中 t 出现的次数.比如aab的去重全排列为aa ...

  4. python3.x中的33个保留字

    Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32 Type " ...

  5. 看外设(uart/spis/i2c/i2s)模块设计

    1.先看外设接口协议. 2.看具体设计文档. 3.仿真case.

  6. 分析laravel的核心日志类

    首先是容器 log对应的是application这个容器 首先我们查看如何获取这个日志类,我们来到\storage\app.php中找到application这个容器,点进去, 我们来到了 点击这个跳 ...

  7. PAT Basic 1043

    1043 输出PATest 给定一个长度不超过 10​4​​ 的.仅由英文字母构成的字符串.请将字符重新调整顺序,按 PATestPATest.... 这样的顺序输出,并忽略其它字符.当然,六种字符的 ...

  8. java 获取音频文件时长

    需要导入jar包:jave 1.0.2 jar 如果是maven项目,在pom.xml文件中添加: <dependency> <groupId>it.sauronsoftwar ...

  9. oracle11gR2下scott用户以及表的建立

    目录 oracle11gR2下scott用户以及表的建立 找到系统带的sql文件(utlsample.sql) 根据SQL的内容操作 新建用户并授权 scott登录 表操作 查询表(使用pl/sql) ...

  10. 关于面试总结-linux篇

    前言 现在做测试的出去面试,都会被问到linux,不会几个linux指令都不好意思说自己是做测试的了,本篇收集了几个被问的频率较高的linux面试题 常用指令 1.说出10个linux常用的指令 ls ...