Link

  https://jzoj.net/senior/#main/show/4216

Description

  给出一个N个整数构成的序列,有M次操作,每次操作有一下三种:

  ①Insert Y X,在序列的第Y个数之前插入一个数X;
  ②Add L R X,对序列中第L个数到第R个数,每个数都加上X;
  ③Query L R,询问序列中第L个数到第R个数的平方和。

Solution

  我不会告诉你这道题我打了10000+byte,并且改了2个月,50多个小时,删掉代码重打了5次。这道题用splay来弄是十分简单的一道裸体。但是我这种渣渣只能用可行的线段树。别人一次能打对,我仍要检查许多线段树的细节,并且打了N多个操作。可能是我代码风格不好吧。但为了方便检查也只好这样了。

30分

  显然,暴力去做,可以拿到拿烂的部分分。

50分
  在30分的基础上,数据增大, 但是没有Insert的操作,所以是线段树裸题。

100分

  大佬肯定是一眼切。这是道Splay练手题目,可以看看gmh大神的题解,异常详细。请允许我打个广告。http://blog.csdn.net/gmh77

  Splay以后我会推进并且更改这个博文。现在我只会线段树。

  对于前两个操作,显然就是线段树裸题,毋庸置疑的。

  但是,因为有了Insert操作,导致我们线段树的下标代表的数不一样。既然在线不可以,离线总是可以的。

  ①线段树1(前缀和)维护位置

  在原本序列的第i个数和i-1个数之间(包括i),插入了多少个数。

  最终用线段树1维护了出来之后,我们很容易的知道了原本序列的数他在最终序列的位置。这是值得你思考的地方

  ②线段树2维护最终序列

  我们知道了原本序列每一个数在最终序列对应的位置,那么理所当然地可以再种一棵线段树2来维护插入的数的最终位置。

  一开始把原序列的数,在最终序列对应位置,标记在线段树那个位置上,0表示当前位置不选,反之。这样一个前缀和就知道最终序列第i个位置之前(包括i)一共出现了多少个数。

  那么每次插入一个数,我们二分出一个i,满足i最小,设1~i前缀和为sum。则满足sum=插入在哪个位置之前-1。这个位置,便是你当前插入的数在最终序列的位置。愉快地记录下来。

  前缀和用线段树2维护。

  这里二分也可以使用线段树二分,*度哗啦啦一大堆。

  如果正着做必然会错。倒着做才是对的。这是你值得思考的。

  ③线段树3,4,5维护最终序列

  我们可以用正常线段树来做了,因为我们可以通过最终位置来确定其对应的线段树下标。

  但是平方和又是一个棘手的问题。

  分解一下。

  (a+b)²=a²+b²+2ab。

  显然,每次加一个数,b就是这个加的数。

  a²为原本的平方和,故用线段树3来维护他。

  2ab,其中如果有多个a,那么就是2b(a1+a2+a3.....+an),那么维护线段树4维护a的和即可。

  还有b²,显然b是已知的,b²直接算即可。但是可能有多个a,那么维护个数即可。

  为什么维护个数?因为有的位置预留了出来但是并没有插入一个数。

  所以就是当前平方和=2*和*加的数+加的数的平方*个数

  和在维护平方和之后再更新。

  细节很多,需要处理,二分有两种,一种是靠右边,一种是靠左边。需要谨慎使用。

  不知道哪里错了最好对拍一下,说不定你就知道了。反正我拍了1天

Code

var
ch:char;
i,j:longint;
n,m,ll,rr,now,len,lll,rrr,midd,lenn:int64;
p,b,r:array[..] of int64;
a:array[..,..] of int64;
num,add:array[..] of int64;
tree:array[..,..] of int64;
procedure build1(root,l,r:longint);
var
mid:longint;
begin
num[root]:=r-l+;
if l=r then
exit; mid:=(l+r) shr ;
build1(root*,l,mid);
build1(root*+,mid+,r); num[root]:=num[root*]+num[root*+];
end; procedure change1(root,l,r:longint);
var
mid:longint;
begin
if (l=r) and (l=ll) then
begin
inc(num[root]);
exit;
end; mid:=(l+r) shr ; if ll<=mid then
change1(root*,l,mid)
else
change1(root*+,mid+,r); num[root]:=num[root*]+num[root*+];
end; procedure find1(root,l,r,x,y:longint);
var
mid:longint;
begin
if (l=x)and(r=y) then
begin
now:=now+num[root]; exit;
end; mid:=(l+r) shr ;
if y<=mid then
find1(root*,l,mid,x,y)
else
if x>mid then
find1(root*+,mid+,r,x,y)
else
begin
find1(root*,l,mid,x,mid);
find1(root*+,mid+,r,mid+,y);
end; num[root]:=num[root*]+num[root*+];
end; procedure build2(root,l,r:longint);
var
mid:longint;
begin
num[root]:=r-l+;
if l=r then
exit; mid:=(l+r) shr ;
build2(root*,l,mid);
build2(root*+,mid+,r); num[root]:=num[root*]+num[root*+];
end; procedure change2(root,l,r:longint);
var
mid:longint;
begin
if (l=r) and (l=ll) then
begin
dec(num[root]);
exit;
end; mid:=(l+r) shr ;
if ll<=mid then
change2(root*,l,mid)
else
change2(root*+,mid+,r); num[root]:=num[root*]+num[root*+];
end; procedure find2(root,l,r,x,y:longint);
var
mid:longint;
begin
if (l=x)and(r=y) then
begin
now:=now+num[root]; exit;
end; mid:=(l+r) shr ;
if y<=mid then
find2(root*,l,mid,x,y)
else
if x>mid then
find2(root*+,mid+,r,x,y)
else
begin
find2(root*,l,mid,x,mid);
find2(root*+,mid+,r,mid+,y);
end; num[root]:=num[root*]+num[root*+];
end; procedure change_ttt(root,l,r,ttt:longint);
var
mid:longint;
begin
if (l=r) and (l=ttt) then
begin
tree[root,]:=p[ttt];
tree[root,]:=p[ttt]*p[ttt];
tree[root,]:=; exit;
end; if tree[root*,]> then
begin
tree[root*,]:=tree[root*,]+tree[root*,]*add[root]*+sqr(add[root])*tree[root*,];
tree[root*,]:=tree[root*,]+add[root]*tree[root*,];
add[root*]:=add[root*]+add[root];
end; if tree[root*+,]> then
begin
tree[root*+,]:=tree[root*+,]+tree[root*+,]*add[root]*+sqr(add[root])*tree[root*+,];
tree[root*+,]:=tree[root*+,]+add[root]*tree[root*+,];
add[root*+]:=add[root*+]+add[root];
end; add[root]:=; mid:=(l+r) shr ;
if ttt<=mid then
change_ttt(root*,l,mid,ttt)
else
change_ttt(root*+,mid+,r,ttt); tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
end;
procedure find_tot(root,l,r,x,y:longint);
var
mid:longint;
begin
if (l=x)and(r=y) then
begin
now:=now+tree[root,]; exit;
end; if tree[root*,]> then
begin
tree[root*,]:=tree[root*,]+tree[root*,]*add[root]*+sqr(add[root])*tree[root*,];
tree[root*,]:=tree[root*,]+add[root]*tree[root*,];
add[root*]:=add[root*]+add[root];
end; if tree[root*+,]> then
begin
tree[root*+,]:=tree[root*+,]+tree[root*+,]*add[root]*+sqr(add[root])*tree[root*+,];
tree[root*+,]:=tree[root*+,]+add[root]*tree[root*+,];
add[root*+]:=add[root*+]+add[root];
end; add[root]:=; mid:=(l+r) shr ;
if y<=mid then
find_tot(root*,l,mid,x,y)
else
if x>mid then
find_tot(root*+,mid+,r,x,y)
else
begin
find_tot(root*,l,mid,x,mid);
find_tot(root*+,mid+,r,mid+,y);
end; tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
end; procedure change(root,l,r,x,y:longint);
var
mid:longint;
begin
if (l=x)and(r=y) then
begin
add[root]:=add[root]+a[i,];
tree[root,]:=tree[root,]+tree[root,]*a[i,]*+sqr(a[i,])*tree[root,];
tree[root,]:=tree[root,]+a[i,]*tree[root,];
exit;
end; if tree[root*,]> then
begin
tree[root*,]:=tree[root*,]+tree[root*,]*add[root]*+sqr(add[root])*tree[root*,];
tree[root*,]:=tree[root*,]+add[root]*tree[root*,];
add[root*]:=add[root*]+add[root];
end; if tree[root*+,]> then
begin
tree[root*+,]:=tree[root*+,]+tree[root*+,]*add[root]*+sqr(add[root])*tree[root*+,];
tree[root*+,]:=tree[root*+,]+add[root]*tree[root*+,];
add[root*+]:=add[root*+]+add[root];
end; add[root]:=; mid:=(l+r)div ;
if y<=mid then
change(root*,l,mid,x,y)
else
if x>mid then
change(root*+,mid+,r,x,y)
else
begin
change(root*,l,mid,x,mid);
change(root*+,mid+,r,mid+,y);
end; tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
end; procedure find(root,l,r,x,y:longint);
var
mid:longint;
begin
if (l=x)and(r=y) then
begin
now:=now+tree[root,]; exit;
end; if tree[root*,]> then
begin
tree[root*,]:=tree[root*,]+tree[root*,]*add[root]*+sqr(add[root])*tree[root*,];
tree[root*,]:=tree[root*,]+add[root]*tree[root*,];
add[root*]:=add[root*]+add[root];
end; if tree[root*+,]> then
begin
tree[root*+,]:=tree[root*+,]+tree[root*+,]*add[root]*+sqr(add[root])*tree[root*+,];
tree[root*+,]:=tree[root*+,]+add[root]*tree[root*+,];
add[root*+]:=add[root*+]+add[root];
end; add[root]:=; mid:=(l+r) shr ;
if y<=mid then
find(root*,l,mid,x,y)
else
if x>mid then
find(root*+,mid+,r,x,y)
else
begin
find(root*,l,mid,x,mid);
find(root*+,mid+,r,mid+,y);
end; tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
tree[root,]:=tree[root*,]+tree[root*+,];
end; function erfen(ppp:longint):longint;
var
ll,rr,midd:longint;
begin
ll:=;
rr:=len;
while ll<rr do
begin
midd:=(ll+rr) shr ; now:=;
find_tot(,,len,,midd); if now>=ppp then
rr:=midd
else
ll:=midd+;
end; exit(ll);
end; begin
readln(n);
for i:= to n do
read(b[i]); len:=n; readln(m); build1(,,n); for i:= to m do
begin
read(ch);
if ch='I' then
begin
while ch<>' ' do
read(ch);
a[i,]:=; readln(a[i,],a[i,]);
ll:=;
rr:=n;
while ll<rr do
begin
midd:=(ll+rr) shr ; now:=;
find1(,,n,,midd);
if now>=a[i,] then
rr:=midd
else
ll:=midd+;
end; change1(,,n); inc(len);
end
else
if ch='A' then
begin
while ch<>' ' do
read(ch); a[i,]:=; readln(a[i,],a[i,],a[i,]);
end
else
begin
while ch<>' ' do
read(ch); a[i,]:=; readln(a[i,],a[i,]);
end;
end; fillchar(num,sizeof(num),); for i:= to len do
p[i]:=maxlongint; build2(,,len); lenn:=len-n; for i:=m downto do
if a[i,]= then
begin
ll:=;
rr:=len;
while ll<rr do
begin
midd:=(ll+rr) shr ; now:=;
find2(,,len,,midd);
if now<a[i,] then
ll:=midd+
else
rr:=midd;
end; r[lenn]:=ll;
p[ll]:=a[i,];
change2(,,len); dec(lenn);
end; lenn:=;
for i:= to len do
if p[i]=maxlongint then
begin
inc(lenn);
p[i]:=b[lenn];
change_ttt(,,len,i);
end; lenn:=;
for i:= to m do
begin
if a[i,]= then
begin
inc(lenn);
change_ttt(,,len,r[lenn]);
end
else
if a[i,]= then
begin
lll:=erfen(a[i,]);
rrr:=erfen(a[i,]); change(,,len,lll,rrr);
end
else
begin
lll:=erfen(a[i,]);
rrr:=erfen(a[i,]); now:=;
find(,,len,lll,rrr); writeln(now mod );
end;
end;
end.

[jzoj]4216.【NOIP2015模拟9.12】平方和的更多相关文章

  1. [JZOJ 4307] [NOIP2015模拟11.3晚] 喝喝喝 解题报告

    题目链接: http://172.16.0.132/senior/#main/show/4307 题目: 解题报告: 题目询问我们没出现坏对的连续区间个数 我们考虑从左到有枚举右端点$r$,判断$a[ ...

  2. JZOJ 4273. 【NOIP2015模拟10.28B组】圣章-精灵使的魔法语

    4273. [NOIP2015模拟10.28B组]圣章-精灵使的魔法语 (File IO): input:elf.in output:elf.out Time Limits: 1000 ms  Mem ...

  3. JZOJ 4269. 【NOIP2015模拟10.27】挑竹签

    4269. [NOIP2015模拟10.27]挑竹签 (File IO): input:mikado.in output:mikado.out Time Limits: 1000 ms  Memory ...

  4. JZOJ 4272. 【NOIP2015模拟10.28B组】序章-弗兰德的秘密

    272. [NOIP2015模拟10.28B组]序章-弗兰德的秘密 (File IO): input:frand.in output:frand.out Time Limits: 1000 ms  M ...

  5. JZOJ 4298. 【NOIP2015模拟11.2晚】我的天

    4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...

  6. JZOJ【NOIP2013模拟联考14】隐藏指令

    JZOJ[NOIP2013模拟联考14]隐藏指令 题目 Description 在d维欧几里得空间中,指令是一个长度为2N的串.串的每一个元素为d个正交基的方向及反方向之一.例如,d = 1时(数轴) ...

  7. 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组

    2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...

  8. 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色

    2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...

  9. 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)

    2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...

随机推荐

  1. PHP-max_execution_time与fpm.request_terminate_timeout介绍

    前段时间一位同事跟我说php脚本超时时间以fpm配置优先.经过自己测试后,其实不然,前面的观点只是在某些情况下成立. php脚本超时时间可以在php.ini的max_execution_time和fp ...

  2. axd文件

    ashx与axd作用相同,ashx一般在本项目内,axd在其它dll中.axd扩展名的必须要在web.config中的<httpHandlers>中进行注册,而ashx直接在项目中当成as ...

  3. word中中文保持正体,英文用斜体的方法.

    有时候,大段的文字中夹杂着英文字母,英文需要斜体,如果一个接一个选中再斜体,费时费力,那么怎样快速实现文斜体中文不斜体呢? 工具/原料 word软件 方法/步骤 选中要修改的段落,替换-查找内容-特殊 ...

  4. AS中的minSdkVersion、compileSdkVersion、targetSdkVersion、buildTools及tools关系和区别

    1.参考文章关于compileSdk.minSdk.targetSdk的文章 http://chinagdg.org/2016/01/picking-your-compilesdkversion-mi ...

  5. Delete from join 用法

    delete (别名) from tblA (别名) left join tblb (别名) on...用法 1.创建使用的表及数据 CREATE TABLE YSHA ( code ), NAME ...

  6. linux 远程 telnet

    linux 远程 telnet [ root@test1 ~]# yum install telnet* (安装的三个包  xinetd . telnet-server.telnet)   [ roo ...

  7. 常见的cmake工程做法

    第一步,创建一个build目录存放cmake生成的中间文件: mkdir build 第二步,进入到build文件目录: cd build 第三步,cmake把代码文件生成一个makefile文件: ...

  8. webpack安装异常

    webpack中文指南:https://zhaoda.net/webpack-handbook/index.html 今天中午,我用   cnpm install   重新下载了一下项目的依赖,爆了一 ...

  9. 线程的start方法和run方法的区别

    run方法及结果 public class MyThread extends Thread { @Override public void run() { System.out.println(&qu ...

  10. HDMI接口之HPD(热拔插)

    HDMI (Pin 19)/DVI(Pin16)的功能是热插拔检测(HPD),这个信号将作为HDMI 源端(Source)是否发起EDID读,是否开始发送TMDS信号的依据.HPD是从HDMI显示器端 ...