题意:

假设你拥有 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. 《算法图解》中涉及的算法的总结及java实现

    该项目源代码已经放到Github上,有兴趣可以点击AlgorithmGraphExample 进行访问 项目启动,项目使用maven搭建,如果不使用maven导入,请保证有Junit4的jar包在工程 ...

  2. strongSwan大坑一直重启(ubuntu)

    报错 Starting strongSwan 5.3.2 IPsec [starter]... charon (20533) started after 40 ms charon stopped af ...

  3. Objective-C分类 (category)和扩展(Extension) 的区别

    http://blog.csdn.net/yhawaii/article/details/6992094 http://blog.163.com/wangy_0223/blog/static/4501 ...

  4. VGG16学习笔记

    转载自:http://deanhan.com/2018/07/26/vgg16/ 摘要 本文对图片分类任务中经典的深度学习模型VGG16进行了简要介绍,分析了其结构,并讨论了其优缺点.调用Keras中 ...

  5. file-leak-detector(文件句柄泄漏)在JDK1.6环境下 weblogic 和 tomcat安装方式以及使用方式

    file-leak-detector作者博客详见: http://file-leak-detector.kohsuke.org/ file-leak-detector学习贴: https://blog ...

  6. Java的jdbc调用SQL Server存储过程Bug201906131120

    如果要查询结果,第一行使用set nocount on;可能可以解决问题.

  7. 思维 || Make It Equal

    http://codeforces.com/contest/1065/problem/C 题意:给你n个高度分别为a[i]的塔,每次可以横着切一刀,切掉不多于k个塔,问最少切多少刀才能把塔切的都一样高 ...

  8. Oracle旗下软件官网下载速度过慢解决办法

    平常下载Oracle旗下软件官网的产品资源,会发现速度很慢,如下载JDK和mysql时, 这样很浪费我们的时间 解决办法: 复制自己需要下载的资源链接 使用迅雷下载该资源 速度均很快 如下载Mysql ...

  9. mysql5.6.35源码安装记录

    mysql数据库源码安装: 源码地址:wget http://mirrors.163.com/mysql/Downloads/MySQL-5.6/mysql-5.6.xx.tar.gz #安装前准备, ...

  10. Redis string类型常用操作

      Redis 有 string.list.set.zset.hash数据类型.string类型是最基础的,其他类型都是在string类型上去建立的,所以了解熟悉string类型的常用操作对于学习re ...