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的代码: 离散 横坐标,然后就二维线段树 空间显然过不了极限数据。时间也过不了。
#include <bits/stdc++.h>
#define U unsigned
using namespace std;
U n,m,t,T,Q,op[][],A[],B[],At,Bt,al,ar,bl,br,s,w,x,ans,a1,a2,b1,b2;
struct ala{ U l,r,p,q,e;}a[];
struct bla{ U l,r,ss,sw,ws,ww;}b[];
void build(U u){
if (a[u].p==a[u].q) return;
U i=a[u].p+a[u].q>>;
a[u].l=++t; a[t].p=a[u].p; a[t].q=i; build(t);
a[u].r=++t; a[t].p=i+; a[t].q=a[u].q; build(t);
}
U finda(U x){
U l=,r=At,j;
while (l<r){
j=l+r+>>;
A[j]<=x?l=j:r=j-;
}
return l;
}
void add(U &u,U p,U q,U l,U r){
if (!u) u=++t;
b[u].sw+=w*(U)(r-l+);
b[u].ss+=s*(U)(r-l+);
if (p==l&&q==r) {
b[u].ws+=s; b[u].ww+=w; return;
}
U i=p+q>>;
if (r<=i) add(b[u].l,p,i,l,r); else
if (l>i) add(b[u].r,i+,q,l,r); else
{add(b[u].l,p,i,l,i); add(b[u].r,i+,q,i+,r);}
}
void play(U u,U l,U r){
if (a[u].p==l&&a[u].q==r){
s=x*(U)(A[r+]-A[l]); w=x;
add(a[u].e,,m,bl,br);
return;
}
s=x*(A[r+]-A[l]); w=; add(a[u].e,,m,bl,br);
U i=a[u].p+a[u].q>>;
if (r<=i) play(a[u].l,l,r); else
if (l>i) play(a[u].r,l,r); else
{play(a[u].l,l,i); play(a[u].r,i+,r);}
}
U getw(U u,U p,U q,U l,U r){
if (!u) return ;
if (p==l&&q==r) return b[u].sw;
U x=(r-l+)*b[u].ww;
U i=p+q>>;
if (r<=i) return getw(b[u].l,p,i,l,r)+x;
if (l>i) return getw(b[u].r,i+,q,l,r)+x;
return getw(b[u].l,p,i,l,i)+getw(b[u].r,i+,q,i+,r)+x;
}
U gets(U u,U p,U q,U l,U r){
if (!u) return ;
if (p==l&&q==r) return b[u].ss;
U x=(r-l+)*b[u].ws;
U i=p+q>>;
if (r<=i) return gets(b[u].l,p,i,l,r)+x;
if (l>i) return gets(b[u].r,i+,q,l,r)+x;
return gets(b[u].l,p,i,l,i)+gets(b[u].r,i+,q,i+,r)+x;
}
U qiu(U u,U l,U r){
if (a[u].p==l&&a[u].q==r) return gets(a[u].e,,m,bl,br);
U x=getw(a[u].e,,m,bl,br)*(A[r+]-A[l]);
U i=a[u].p+a[u].q>>;
if (r<=i) return x+qiu(a[u].l,l,r);
if (l>i) return x+qiu(a[u].r,l,r);
return x+qiu(a[u].l,l,i)+qiu(a[u].r,i+,r);
}
U qiuw(U u,U l,U r){
if (a[u].p==l&&a[u].q==r) return getw(a[u].e,,m,bl,br);
U x=getw(a[u].e,,m,bl,br);
U i=a[u].p+a[u].q>>;
if (r<=i) return x+qiuw(a[u].l,l,r);
if (l>i) return x+qiuw(a[u].r,l,r);
return x+qiuw(a[u].l,l,i)+qiuw(a[u].r,i+,r);
}
int main(){
scanf("%u%u%u%u",&n,&m,&T,&Q);
for (U i=;i<=T;++i){
scanf("%u%u%u%u%u",&op[i][],&op[i][],&op[i][],&op[i][],&op[i][]);
if (op[i][]>op[i][]) swap(op[i][],op[i][]);
if (op[i][]>op[i][]) swap(op[i][],op[i][]);
A[i]=op[i][]; A[i+T]=op[i][]+;
}
A[T+T+]=;
sort(A+,A+T+T+);
for (U i=;i<=T+T+;++i){
if (A[i]!=A[i-]) ++At;
A[At]=A[i];
}
a[].p=; a[].q=At; build(t=); t=;
A[At+]=n+;
for (U i=;i<=T;++i){
al=finda(op[i][]); ar=finda(op[i][]);
bl=op[i][]; br=op[i][];
x=op[i][]; play(,al,ar);
}
while (Q--){
scanf("%u%u",&a2,&br);
a1=ans%n+; a2=(ans+a2)%n+;
bl=ans%m+; br=(ans+br)%m+;
if (a1>a2) swap(a1,a2);
if (bl>br) swap(bl,br);
al=finda(a1); ar=finda(a2); ans=;
if (al==ar)
ans=qiuw(,al,al)*(a2-a1+);
else{
if (al+<ar) ans+=qiu(,al+,ar-);
ans+=qiuw(,al,al)*(A[al+]-a1);
ans+=qiuw(,ar,ar)*(a2-A[ar]+);
}
printf("%u\n",ans);
}
return ;
}
Bad Apple!!
实际 只要主席树就可以一个log了。 对第一维排序离散,另一维动态开点主席树。记录到A这个坐标的 前缀信息和当前信息。
一个重要的事故。。输入的操作。数据范围有很多问题。。具体看代码
#include <bits/stdc++.h>
#define U unsigned
#define Ul unsigned long long
using namespace std;
struct opt{ U x,p,q; Ul w; }op[];
struct bla{ U l,r; Ul a,qs,ds,qw,dw; }b[];
bool cmp(opt a,opt b){return a.x<b.x;}
U n,m,T,Q,t,e[]; Ul A,W,ans,ax,bx,ay,by;
void add(U &u,U l,U r,U p,U q){
b[++t]=b[u]; u=t;
b[u].qs+=b[u].ds*(A-b[u].a);
b[u].qw+=b[u].dw*(A-b[u].a);
b[u].a=A; b[u].ds+=W*(r-l+);
if (l==p&&r==q){ b[u].dw+=W; return; }
U i=p+q>>;
if (r<=i) add(b[u].l,l,r,p,i); else
if (l>i) add(b[u].r,l,r,i+,q); else
{add(b[u].l,l,i,p,i); add(b[u].r,i+,r,i+,q);}
}
Ul get(U u,U l,U r,U p,U q){
if (!u) return ;
if (l==p&&q==r) return b[u].qs+b[u].ds*(A-b[u].a);
Ul ans=(b[u].qw+b[u].dw*(A-b[u].a))*(r-l+);
U i=p+q>>;
if (r<=i) return get(b[u].l,l,r,p,i)+ans;
if (l>i) return get(b[u].r,l,r,i+,q)+ans;
return get(b[u].l,l,i,p,i)+get(b[u].r,i+,r,i+,q)+ans;
}
Ul qiu(U x){
U l=,r=T,j; if (x<op[].x) return ;
if (x>=op[r].x) x=op[r].x;
while (l<r){
j=l+r+>>;
op[j].x<=x?l=j:r=j-;
}
A=x+; return get(e[l],ay,by,,m);
}
int main(){
scanf("%u%u%u%u",&n,&m,&T,&Q);
for (U i=;i<=T;++i){
U a,b,c,d; Ul e;
scanf("%u%u%u%u%llu",&a,&b,&c,&d,&e);
a=min(max((U),a),n); b=min(max((U),b),n);
c=min(max((U),c),m); d=min(max((U),d),m);
if (a>b) swap(a,b); if (c>d) swap(c,d);
op[i]={a,c,d,e}; op[i+T]={b+,c,d,-e};
} T<<=;
sort(op+,op++T,cmp);
for (U i=;i<=T;++i) A=op[i].x,W=op[i].w,e[i]=e[i-],add(e[i],op[i].p,op[i].q,,m);
while (Q--){
scanf("%llu%llu",&bx,&by);
ax=ans%n+; ay=ans%m+; bx=(ans+bx)%n+; by=(ans+by)%m+;
if (ax>bx) swap(ax,bx); if (ay>by) swap(ay,by);
ans=qiu(bx)-qiu(ax-); printf("%llu\n",ans);
}
return ;
}
Good Apple!!!
BZOJ2874 训练士兵 主席树的更多相关文章
- 2019.01.22 bzoj2874: 训练士兵(主席树)
传送门 题意简述:给出一个n∗mn*mn∗m的矩阵n,m≤1e8n,m\le1e8n,m≤1e8,支持矩形加,矩形求和,强制在线. 思路:第一眼二维动态开点线段树,上网去搜有没有这种做法发现会被卡时空 ...
- BZOJ2874 : 训练士兵
设$a[i][j]$表示$(i,j)$右下角要增加多少 $aj[i][j]=a[i][j]\times j$ $ai[i][j]=a[i][j]\times i$ $aij[i][j]=a[i][j] ...
- HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分)
HDU6621 K-th Closest Distance HDU2019多校训练第四场 1008(主席树+二分) 传送门:http://acm.hdu.edu.cn/showproblem.php? ...
- Cutting Bamboos(2019年牛客多校第九场H题+二分+主席树)
题目链接 传送门 题意 有\(n\)棵竹子,然后有\(q\)次操作,每次操作给你\(l,r,x,y\),表示对\([l,r]\)区间的竹子砍\(y\)次,每次砍伐的长度和相等(自己定砍伐的高度\(le ...
- K-th Number Poj - 2104 主席树
K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...
- 集训队8月1日(拓扑排序+DFS+主席树入门)
上午看书总结 今天上午我看了拓扑排序,DFS+剪枝,相当于回顾了一下,写了三个比较好的例题.算法竞赛指南93~109页. 1.状态压缩+拓扑排序 https://www.cnblogs.com/246 ...
- bzoj3207--Hash+主席树
题目大意: 给定一个n个数的序列和m个询问(n,m<=100000)和k,每个询问包含k+2个数字:l,r,b[1],b[2]...b[k],要求输出b[1]~b[k]在[l,r]中是否出现. ...
- bzoj1901--树状数组套主席树
树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
随机推荐
- [Go]链表的相关知识
切片有着占用内存少喝创建便捷等特点,但它本质上还是数组.切片的一大好处是可以通过窗口快速地定位并获取或者修改底层数组中的元素.不过当删除切片中的元素的时候就没那么简单了.元素复制一般是免不了的,就算只 ...
- [luoguP2513] [HAOI2009]逆序对数列(DP)
传送门 f[i][j]表示前i个数,逆序对数为j的答案 则DP方程为: f[1][0] = 1; for(i = 2; i <= n; i++) for(j = 0; j <= m; j+ ...
- [luoguP2184] 贪婪大陆(树状数组)
传送门 用两个树状数组,cr 维护 1....x 中 r 的数量 cl 维护 1....x 中 l 的数量 求答案的时候只需要求 y 前面 被作为左端点 的个数 - x 前面 被作为右端点的个数 —— ...
- poj 3683 2-sat问题,输出任意一组可行解
/* 2sat问题 输出任意一组可行解 */ #include<stdio.h> #include<string.h> #include<stdlib.h> #in ...
- vagrant的学习 之 Yii2
vagrant的学习 之 Yii2 本文根据慕课网的视频教程练习,感谢慕课网! 慕课视频学习地址:https://www.imooc.com/video/14218. 慕课的参考文档地址:https: ...
- Python中排序的灵活使用
Python中列表按指定标准排序实例 概述 本题需要先输入机器的数目和任务的数目. 在接下来的n行中每行分别包含机器的最大执行时间和机器所能执行任务的最大强度. 在接下来的n行中每行分别包含任务执行时 ...
- $.post()用法例子
1:删除用户操作 $('.delete').click(function(){ var classid=$(this).parent().siblings().eq(0).children().val ...
- BZOJ——T 1707: [Usaco2007 Nov]tanning分配防晒霜
http://www.lydsy.com/JudgeOnline/problem.php?id=1707 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 8 ...
- Lca 之倍增算法
引入: 比如说要找树上任意两个点的路上的最大值.如果是一般的做法 会 接近o(n)的搜,从一个点搜到另一个点,但是如果询问多了复杂度就很高了. 然后我们会预处理.预处理是o(n²)的,询问是o(1)的 ...
- Java并发包——Atomic操作
Java并发包——Atomic操作 摘要:本文主要学习了Java并发包下的atomic包中有关原子操作的一些类. 部分内容来自以下博客: https://blog.csdn.net/qq_303796 ...