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!!

 

实际 只要主席树就可以一个log了。 对第一维排序离散,另一维动态开点主席树。记录到A这个坐标的 前缀信息和当前信息。

一个重要的事故。。输入的操作。数据范围有很多问题。。具体看代码

 1 #include <bits/stdc++.h>
 2 #define U unsigned
 3 #define Ul unsigned long long
 4 using namespace std;
 5 struct opt{ U x,p,q; Ul w; }op[80005];
 6 struct bla{ U l,r; Ul a,qs,ds,qw,dw; }b[5000005];
 7 bool cmp(opt a,opt b){return a.x<b.x;}    
 8 U n,m,T,Q,t,e[80005]; Ul A,W,ans,ax,bx,ay,by;
 9 void add(U &u,U l,U r,U p,U q){
10     b[++t]=b[u]; u=t;
11     b[u].qs+=b[u].ds*(A-b[u].a);
12     b[u].qw+=b[u].dw*(A-b[u].a);
13     b[u].a=A; b[u].ds+=W*(r-l+1);
14     if (l==p&&r==q){ b[u].dw+=W; return; }
15     U i=p+q>>1;
16     if (r<=i) add(b[u].l,l,r,p,i); else
17     if (l>i) add(b[u].r,l,r,i+1,q); else
18      {add(b[u].l,l,i,p,i); add(b[u].r,i+1,r,i+1,q);}
19 }
20 Ul get(U u,U l,U r,U p,U q){
21     if (!u) return 0;
22     if (l==p&&q==r) return b[u].qs+b[u].ds*(A-b[u].a);
23     Ul ans=(b[u].qw+b[u].dw*(A-b[u].a))*(r-l+1);
24     U i=p+q>>1;
25     if (r<=i) return get(b[u].l,l,r,p,i)+ans;
26     if (l>i) return get(b[u].r,l,r,i+1,q)+ans;
27     return get(b[u].l,l,i,p,i)+get(b[u].r,i+1,r,i+1,q)+ans;
28 }
29 Ul qiu(U x){
30     U l=1,r=T,j; if (x<op[1].x) return 0;
31     if (x>=op[r].x) x=op[r].x;
32     while (l<r){
33         j=l+r+1>>1;
34         op[j].x<=x?l=j:r=j-1;
35     }
36     A=x+1; return get(e[l],ay,by,1,m);
37 }
38 int main(){
39     scanf("%u%u%u%u",&n,&m,&T,&Q);
40     for (U i=1;i<=T;++i){
41         U a,b,c,d; Ul e;
42         scanf("%u%u%u%u%llu",&a,&b,&c,&d,&e);
43         a=min(max((U)1,a),n); b=min(max((U)1,b),n);
44         c=min(max((U)1,c),m); d=min(max((U)1,d),m);
45         if (a>b) swap(a,b); if (c>d) swap(c,d);
46         op[i]={a,c,d,e}; op[i+T]={b+1,c,d,-e};
47     } T<<=1;
48     sort(op+1,op+1+T,cmp);
49     for (U i=1;i<=T;++i) A=op[i].x,W=op[i].w,e[i]=e[i-1],add(e[i],op[i].p,op[i].q,1,m);
50     while (Q--){
51         scanf("%llu%llu",&bx,&by);
52         ax=ans%n+1; ay=ans%m+1; bx=(ans+bx)%n+1; by=(ans+by)%m+1;
53         if (ax>bx) swap(ax,bx); if (ay>by) swap(ay,by);
54         ans=qiu(bx)-qiu(ax-1); printf("%llu\n",ans);
55     }
56     return 0;
57 }
Good Apple!!!

 

转载于:https://www.cnblogs.com/cyz666/p/6645030.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值