BZOJ2874 训练士兵 主席树

【啊 首先 这是道权限题,然后本人显然是没有权限的  23咳3】

最近数据结构做的越来越少。。然后 就跟上次一样 ,一做就是三四种不同写法。

等价的题面:

最近GY大神在sc2的天梯中被神族虐得很惨,表示很不爽。ryz决定帮助GY大神练习散枪兵技术。GY生产了n*m个枪兵,并站成了一个大小为n*m的方阵。ryz生产了t个电兵(高阶圣堂武士),每个电兵能对一个矩形区域造成一定的AOE伤害(也就是对该矩形区域的每个枪兵都造成相等的伤害)。但是ryz的电兵实在太多了,以至于GY无法快速计算出一个矩形区域内枪兵受到的总伤害,于是他就不知道应该优先操作哪个位置的枪兵了。虽然GY大神只要1分钟就可以秒掉这道题,但是由于他正在操作枪兵,你需要写一个程序帮他解决这个问题。

输入格式:

第一行四个正整数n,m,t,q。
接下来t行,每行描述一个电兵。每行包括5个正整数x1,x2,y1,y2,d,表示对所有符合x1<=x<=x2,y1<=y<=y2的每个枪兵造成了d点伤害。
为了让同学们写更为有趣的在线询问算法,我把询问加密了,第1个询问的密码为0,第i+1个询问的密码为第i个询问的答案(mod 2^32)。
接下来q行,每行描述一个询问。每行包括2个正整数x,y。x1,x2,y1,y2按照以下方法计算(c表示该询问的密码):
x1=c % n+1,x2=(c+x) % n+1,如果x1>x2则交换x1和x2
y1=c % m+1,y2=(c+y) % m +1,如果y1>y2则交换y1和y2
你需要输出所有x1<=x<=x2,y1<=y<=y2的枪兵受到的总伤害(mod 2^32)。

输出格式:

对于每一个询问,输出一行答案mod 2^32的值。

样例输入:

4 5 3 2
1 3 2 2 7
2 4 2 3 5
1 4 4 5 6
1 2
0 3

样例输出:

24
12

数据范围:

对于20%的数据,m<=10
对于40%的数据,n,m<=50000,t<=30000,q<=30000
对于60%的数据,n,m<=10^5
对于另外20%的数据,所有电兵的y2-y1<=3
对于100%的数据,n,m<=10^8,t<=40000,q<=150000,d<=100000

时间限制:

5-6S  (这时间应该是按测试点给的吧。。)

空间限制:

1G  (exm?!)

作为曾经的数据结构狂热者。。现在大概是手感褪色。。

看到题 臆想 log方 ——好、裸题。 然后码农 最后GG。

那么 上一个GG的代码: 离散 横坐标,然后就二维线段树 空间显然过不了极限数据。时间也过不了。

  1 #include <bits/stdc++.h>
  2 #define U unsigned
  3 using namespace std;
  4 U n,m,t,T,Q,op[40005][5],A[80006],B[80006],At,Bt,al,ar,bl,br,s,w,x,ans,a1,a2,b1,b2;
  5 struct ala{ U l,r,p,q,e;}a[320050];
  6 struct bla{ U l,r,ss,sw,ws,ww;}b[50000000];
  7 void build(U u){
  8     if (a[u].p==a[u].q) return;
  9     U i=a[u].p+a[u].q>>1;
 10     a[u].l=++t; a[t].p=a[u].p; a[t].q=i; build(t);
 11     a[u].r=++t; a[t].p=i+1; a[t].q=a[u].q; build(t);
 12 }
 13 U finda(U x){
 14     U l=1,r=At,j;
 15     while (l<r){
 16         j=l+r+1>>1;
 17         A[j]<=x?l=j:r=j-1;
 18     }
 19     return l;
 20 }
 21 void add(U &u,U p,U q,U l,U r){
 22     if (!u) u=++t;
 23     b[u].sw+=w*(U)(r-l+1);
 24     b[u].ss+=s*(U)(r-l+1);
 25     if (p==l&&q==r) {
 26         b[u].ws+=s; b[u].ww+=w; return;
 27     }
 28     U i=p+q>>1;
 29     if (r<=i) add(b[u].l,p,i,l,r); else
 30     if (l>i) add(b[u].r,i+1,q,l,r); else
 31     {add(b[u].l,p,i,l,i); add(b[u].r,i+1,q,i+1,r);}
 32 }
 33 void play(U u,U l,U r){
 34     if (a[u].p==l&&a[u].q==r){
 35         s=x*(U)(A[r+1]-A[l]); w=x;
 36         add(a[u].e,1,m,bl,br);
 37         return;
 38     }
 39     s=x*(A[r+1]-A[l]); w=0; add(a[u].e,1,m,bl,br);
 40     U i=a[u].p+a[u].q>>1;
 41     if (r<=i) play(a[u].l,l,r); else
 42     if (l>i) play(a[u].r,l,r); else
 43     {play(a[u].l,l,i); play(a[u].r,i+1,r);}
 44 }
 45 U getw(U u,U p,U q,U l,U r){
 46     if (!u) return 0;
 47     if (p==l&&q==r) return b[u].sw;
 48     U x=(r-l+1)*b[u].ww;
 49     U i=p+q>>1;
 50     if (r<=i) return getw(b[u].l,p,i,l,r)+x;
 51     if (l>i) return getw(b[u].r,i+1,q,l,r)+x;
 52     return getw(b[u].l,p,i,l,i)+getw(b[u].r,i+1,q,i+1,r)+x;
 53 }
 54 U gets(U u,U p,U q,U l,U r){
 55     if (!u) return 0;
 56     if (p==l&&q==r) return b[u].ss;
 57     U x=(r-l+1)*b[u].ws;
 58     U i=p+q>>1;
 59     if (r<=i) return gets(b[u].l,p,i,l,r)+x;
 60     if (l>i) return gets(b[u].r,i+1,q,l,r)+x;
 61     return gets(b[u].l,p,i,l,i)+gets(b[u].r,i+1,q,i+1,r)+x;
 62 }
 63 U qiu(U u,U l,U r){
 64     if (a[u].p==l&&a[u].q==r) return gets(a[u].e,1,m,bl,br);
 65     U x=getw(a[u].e,1,m,bl,br)*(A[r+1]-A[l]);
 66     U i=a[u].p+a[u].q>>1;
 67     if (r<=i) return x+qiu(a[u].l,l,r);
 68     if (l>i) return x+qiu(a[u].r,l,r);
 69     return x+qiu(a[u].l,l,i)+qiu(a[u].r,i+1,r);
 70 }
 71 U qiuw(U u,U l,U r){
 72     if (a[u].p==l&&a[u].q==r) return getw(a[u].e,1,m,bl,br);
 73     U x=getw(a[u].e,1,m,bl,br);
 74     U i=a[u].p+a[u].q>>1;
 75     if (r<=i) return x+qiuw(a[u].l,l,r);
 76     if (l>i) return x+qiuw(a[u].r,l,r);
 77     return x+qiuw(a[u].l,l,i)+qiuw(a[u].r,i+1,r);
 78 }
 79 int main(){
 80     scanf("%u%u%u%u",&n,&m,&T,&Q);
 81     for (U i=1;i<=T;++i){
 82         scanf("%u%u%u%u%u",&op[i][0],&op[i][1],&op[i][2],&op[i][3],&op[i][4]);
 83         if (op[i][0]>op[i][1]) swap(op[i][0],op[i][1]);
 84         if (op[i][2]>op[i][3]) swap(op[i][2],op[i][3]);
 85         A[i]=op[i][0]; A[i+T]=op[i][1]+1;
 86     }
 87     A[T+T+1]=1;
 88     sort(A+1,A+T+T+2);
 89     for (U i=1;i<=T+T+1;++i){
 90         if (A[i]!=A[i-1]) ++At;
 91         A[At]=A[i];
 92     }
 93     a[1].p=1; a[1].q=At; build(t=1); t=0;
 94     A[At+1]=n+1;
 95     for (U i=1;i<=T;++i){
 96         al=finda(op[i][0]); ar=finda(op[i][1]);
 97         bl=op[i][2]; br=op[i][3];
 98         x=op[i][4]; play(1,al,ar);
 99     }
100     while (Q--){
101         scanf("%u%u",&a2,&br);
102         a1=ans%n+1; a2=(ans+a2)%n+1;
103         bl=ans%m+1; br=(ans+br)%m+1;
104         if (a1>a2) swap(a1,a2);
105         if (bl>br) swap(bl,br);
106         al=finda(a1); ar=finda(a2); ans=0;
107         if (al==ar)
108             ans=qiuw(1,al,al)*(a2-a1+1);
109         else{
110             if (al+1<ar) ans+=qiu(1,al+1,ar-1);
111             ans+=qiuw(1,al,al)*(A[al+1]-a1);
112             ans+=qiuw(1,ar,ar)*(a2-A[ar]+1);
113         }
114         printf("%u\n",ans);
115     }
116     return 0;
117 }

Bad Apple!!

时间: 2024-08-04 11:56:52

BZOJ2874 训练士兵 主席树的相关文章

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