【BZOJ2874】训练士兵(主席树)

题意:有一个N*M的矩阵,给出一些形如(x1,y1,x2,y2,s)的操作,代表(x1,y1)到(x2,y2)都被加上了s这个数

现在有一些强制在线的询问,询问(x1,y1)到(x2,y2)的和

对于100%的数据 n,m<=10^8,k<=40000,q<=100000;

思路:将操作(x1,y1,x2,y2,s)差分成

(x1,y1)+s

(x1,y2+1)-s

(x2+1,y1)-s

(x2+1,y2+1)+s

四个点

以下是推导过程:

可以看出只需维护a[i,j],a[i,j]*i,a[i,j]*j,a[i,j]*i*j四个值的二维前缀和

从左到右,从上到下排序并离散化,对每一行建立一棵主席树表示左上角的前缀和,

询问时在主席树中查找一段从头开始的前缀和即可

  1 var t:array[0..6000000,1..6]of int64;
  2     root:array[0..600000]of int64;
  3     c:array[1..300000,1..3]of int64;
  4     cx,cy:array[1..300000]of int64;
  5     n,m,i,j,u,k,cnt,u1,u2,k1,q1,tmp,x,y:longint;
  6     ans,x1,y1,x2,y2:int64;
  7
  8 procedure swap(var x,y:int64);
  9 var t:int64;
 10 begin
 11  t:=x; x:=y; y:=t;
 12 end;
 13
 14 procedure qsortx(l,r:longint);
 15 var i,j,mid:longint;
 16 begin
 17  i:=l; j:=r; mid:=cx[(l+r)>>1];
 18  repeat
 19   while mid>cx[i] do inc(i);
 20   while mid<cx[j] do dec(j);
 21   if i<=j then
 22   begin
 23    swap(cx[i],cx[j]);
 24    inc(i); dec(j);
 25   end;
 26  until i>j;
 27  if l<j then qsortx(l,j);
 28  if i<r then qsortx(i,r);
 29 end;
 30
 31 procedure qsorty(l,r:longint);
 32 var i,j,mid:longint;
 33 begin
 34  i:=l; j:=r; mid:=cy[(l+r)>>1];
 35  repeat
 36   while mid>cy[i] do inc(i);
 37   while mid<cy[j] do dec(j);
 38   if i<=j then
 39   begin
 40    swap(cy[i],cy[j]);
 41    inc(i); dec(j);
 42   end;
 43  until i>j;
 44  if l<j then qsorty(l,j);
 45  if i<r then qsorty(i,r);
 46 end;
 47
 48 function hashx(x:longint):longint;
 49 var l,r,mid,last:longint;
 50 begin
 51  l:=1; r:=u1; last:=0;
 52  while l<=r do
 53  begin
 54   mid:=(l+r)>>1;
 55   if x>=cx[mid] then begin last:=mid; l:=mid+1; end
 56    else r:=mid-1;
 57  end;
 58  exit(last);
 59 end;
 60
 61 function hashy(x:longint):longint;
 62 var l,r,mid,last:longint;
 63 begin
 64  l:=1; r:=u2; last:=0;
 65  while l<=r do
 66  begin
 67   mid:=(l+r)>>1;
 68   if x>=cy[mid] then begin last:=mid; l:=mid+1; end
 69    else r:=mid-1;
 70  end;
 71  exit(last);
 72 end;
 73
 74 procedure qsort(l,r:longint);
 75 var i,j,mid1,mid2:longint;
 76 begin
 77  i:=l; j:=r; mid1:=c[(l+r)>>1,1]; mid2:=c[(l+r)>>1,2];
 78  repeat
 79   while (mid1>c[i,1])or((mid1=c[i,1])and(mid2>c[i,2])) do inc(i);
 80   while (mid1<c[j,1])or((mid1=c[j,1])and(mid2<c[j,2])) do dec(j);
 81   if i<=j then
 82   begin
 83    swap(c[i,1],c[j,1]);
 84    swap(c[i,2],c[j,2]);
 85    swap(c[i,3],c[j,3]);
 86    inc(i); dec(j);
 87   end;
 88  until i>j;
 89  if l<j then qsort(l,j);
 90  if i<r then qsort(i,r);
 91 end;
 92
 93 function query(p,l,r,x,y:longint):int64;
 94 var mid:longint;
 95 begin
 96  if x=0 then exit(0);
 97  if p=0 then exit(0);
 98  if x>=r then exit(t[p,y]);
 99  mid:=(l+r)>>1;
100  if x<=mid then exit(query(t[p,5],l,mid,x,y))
101   else exit(t[t[p,5],y]+query(t[p,6],mid+1,r,x,y));
102 end;
103
104 function ask(x,y:longint):int64;
105 var x1,y1:longint;
106 begin
107  x1:=hashx(x); y1:=hashy(y);
108  ask:=0;
109  ask:=ask+query(root[x1],1,u2,y1,1)*(x+1)*(y+1);
110  ask:=ask-query(root[x1],1,u2,y1,2)*(y+1);
111  ask:=ask-query(root[x1],1,u2,y1,3)*(x+1);
112  ask:=ask+query(root[x1],1,u2,y1,4);
113 end;
114
115 procedure update(var p:int64;l,r,x:longint;v:int64;x1,y1:longint);
116 var mid:longint;
117 begin
118  inc(cnt); t[cnt]:=t[p];
119  p:=cnt;
120  t[cnt,1]:=t[cnt,1]+v;
121  t[cnt,2]:=t[cnt,2]+v*x1;
122  t[cnt,3]:=t[cnt,3]+v*y1;
123  t[cnt,4]:=t[cnt,4]+v*x1*y1;
124  if l=r then exit;
125  mid:=(l+r)>>1;
126  if x<=mid then update(t[p,5],l,mid,x,v,x1,y1)
127   else update(t[p,6],mid+1,r,x,v,x1,y1);
128 end;
129
130 begin
131  assign(input,‘bzoj2874.in‘); reset(input);
132  assign(output,‘bzoj2874.out‘); rewrite(output);
133  readln(n,m,k1,q1);
134  k:=0;
135  for i:=1 to k1 do
136  begin
137   read(x1); read(x2); read(y1); read(y2); read(tmp);
138   inc(k); c[k,1]:=x1; c[k,2]:=y1; c[k,3]:=tmp;
139   inc(k); c[k,1]:=x1; c[k,2]:=y2+1; c[k,3]:=-tmp;
140   inc(k); c[k,1]:=x2+1; c[k,2]:=y1; c[k,3]:=-tmp;
141   inc(k); c[k,1]:=x2+1; c[k,2]:=y2+1; c[k,3]:=tmp;
142   inc(u); cx[u]:=x1; cy[u]:=y1;
143   inc(u); cx[u]:=x2+1; cy[u]:=y2+1;
144  end;
145  qsortx(1,u); qsorty(1,u);
146  u1:=1;
147  for i:=2 to u do
148   if cx[i]<>cx[u1] then begin inc(u1); cx[u1]:=cx[i]; end;
149  u2:=1;
150  for i:=2 to u do
151   if cy[i]<>cy[u2] then begin inc(u2); cy[u2]:=cy[i]; end;
152
153  qsort(1,k);
154  j:=1;
155  for i:=1 to u1 do
156  begin
157   root[i]:=root[i-1];
158   while (j<=k)and(hashx(c[j,1])=i) do
159   begin
160    update(root[i],1,u2,hashy(c[j,2]),c[j,3],c[j,1],c[j,2]);
161    inc(j);
162   end;
163  end;
164  for i:=1 to q1 do
165  begin
166   readln(x,y);
167   x1:=ans mod n+1; x2:=(ans+x) mod n+1; if x1>x2 then swap(x1,x2);
168   y1:=ans mod m+1; y2:=(ans+y) mod m+1; if y1>y2 then swap(y1,y2);
169   ans:=ask(x2,y2)-ask(x1-1,y2)-ask(x2,y1-1)+ask(x1-1,y1-1);
170   writeln(ans);
171  end;
172  close(input);
173  close(output);
174 end.
时间: 2024-08-09 00:52:41

【BZOJ2874】训练士兵(主席树)的相关文章

BZOJ2874 训练士兵 主席树

[啊 首先 这是道权限题,然后本人显然是没有权限的  23咳3] 最近数据结构做的越来越少..然后 就跟上次一样 ,一做就是三四种不同写法. 等价的题面: 最近GY大神在sc2的天梯中被神族虐得很惨,表示很不爽.ryz决定帮助GY大神练习散枪兵技术.GY生产了n*m个枪兵,并站成了一个大小为n*m的方阵.ryz生产了t个电兵(高阶圣堂武士),每个电兵能对一个矩形区域造成一定的AOE伤害(也就是对该矩形区域的每个枪兵都造成相等的伤害).但是ryz的电兵实在太多了,以至于GY无法快速计算出一个矩形区

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)

HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分) 传送门:http://acm.hdu.edu.cn/showproblem.php?pid=6621 题意: 给你n个数,有m次询问 每次问你在区间[l,r]内 第k小的|\(a_i-p\)|是多少 题解: 主席树+二分 每次二分答案 如果p+mid到p-mid的值的个数大于k个的话,mid值就是可行了,然后缩小区间往左找即可 因为保证有解,所以二分出来的mid值就是答案了 que

[poj2104]可持久化线段树入门题(主席树)

解题关键:离线求区间第k小,主席树的经典裸题: 对主席树的理解:主席树维护的是一段序列中某个数字出现的次数,所以需要预先离散化,最好使用vector的erase和unique函数,很方便:如果求整段序列的第k小,我们会想到离散化二分和线段树的做法, 而主席树只是保存了序列的前缀和,排序之后,对序列的前缀分别做线段树,具有差分的性质,因此可以求任意区间的第k小,如果主席树维护索引,只需要求出某个数字在主席树中的位置,即为sort之后v中的索引:若要求第k大,建树时反向排序即可 1 #include

【BZOJ 3551】[ONTAK2010] Peaks加强版 Kruskal重构树+树上倍增+主席树

这题真刺激...... I.关于Kruskal重构树,我只能开门了,不过补充一下那玩意还是一棵满二叉树.(看一下内容之前请先进门坐一坐) II.原来只是用树上倍增求Lca,但其实树上倍增是一种方法,Lca只是他的一种应用,他可以搞各种树上问题,树上倍增一般都会用到f数组. |||.我们跑出来dfs序就能在他的上面进行主席树了. IV.别忘了离散. V.他可能不连通,我一开始想到了,但是我觉得出题人可能会是好(S)人(B),但是...... #include <cstdio> #include

[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]

Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为Pi.同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同.调度系统会经常向 查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个 )的优先级之和是多少.特别的,如

BZOJ_3207_花神的嘲讽计划1_(Hash+主席树)

描述 http://www.lydsy.com/JudgeOnline/problem.php?id=3207 给出一个长度为\(n\)的串,以及\(m\)个长度为\(k\)的串,求每个长度为\(k\)的串在原串\([x,y]\)区间是否出现过. 分析 这道题要求对比长度为\(k\)的串,于是我们把这些串的Hash值都算出来,问题就转化成了求\([x,y]\)的区间中是否出现过某Hash值. 求区间中某一个值出现了多少次,可以用主席树. p.s. 1.学习了主席树指针的写法,比数组慢好多啊...

[主席树]ZOJ3888 Twelves Monkeys

题意:有n年,其中m年可以乘时光机回到过去,q个询问 下面m行,x,y 表示可以在y年穿越回x年, 保证y>x 下面q个询问, 每个询问有个年份k 问的是k年前面 有多少年可以通过一种以上($\ge 2$)方法穿越回去的, 其中时光机只能用一次 比如案例 9 3 3 9 1 6 1 4 1 6 7 2 如图 对于询问 6这一年:1.穿越回第1年  2.等时间过呀过呀过到第9年,再穿越回第1年 那么第1年就有两种方法可以穿越回去, 同理, 2.3.4年也有同样两种方法(回到1再等时间过呀过 过到2

POJ2104主席树模板题

完成新成就——B站上看了算法https://www.bilibili.com/video/av4619406/?from=search&seid=17909472848554781180#page=2 K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 60158   Accepted: 21054 Case Time Limit: 2000MS Description You are working

【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树

题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高速光缆组成.每个部门都有一个专属的路由器,部门局域网内的所有机器都联向这个路由器,然后再通过这个通信子网与其他部门进行通信联络.该网络结构保证网络中的任意两个路由器之间都存在一条直接或间接路径以进行通信. 高速光缆的数据传输速度非常快,以至于利用光缆传输的延迟时间可以忽略.但是由于路由器老化,在这些

主席树

#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <cstdlib> #define maxn 100005 using namespace std; int b[maxn],t[maxn],n,m,size,v[maxn],tot