GDKOI2016 魔卡少女

Description

君君是中山大学的四年级学生。有一天在家不小心开启了放置在爸爸书房中的一本古书。于是,君君把放在书中最上面的一张牌拿出来观摩了一下,突然掀起一阵大风把书中的其她所有牌吹散到各地。这时一只看上去四不像的可爱生物“封印之兽”可鲁贝洛斯从书中钻了出来,它告诉君君书中的牌叫“库洛牌”,现在散落各地已实体化,要君君将它们全部再次封印起来,以免危害世界,于是君君开始过上了收服“库洛牌”的旅程。
经过不懈努力,君君集齐了N 张库洛牌,最后的审判就要来临,为了战胜审判者月,君君开始研究起这N 张库洛牌的魔法效果。君君已经将N 张库洛牌从左到右依次排列好,这N 张库洛牌的魔法值从左到右依次为a1; a2; a3; …aN。她将告诉你这N 张库洛牌的魔法值。在最后的审判时,审判者月将会选择一个区间进行PK,君君预测了可能进行PK 的若干区间,她想请你帮助她计算这些区间的魔法效果,以便她更好地布置战术。一个区间内,所有连续子序列都会产生魔法效果。一个连续子序列p1; p2; p3; …; pk 的魔法效果定义为p1^p2^p3^…^pk(^表示异或)。一个区间的魔法效果定义为所有连续子序列的魔法效果的和。例如有5 张库洛牌,魔法值为1; 1; 2; 4; 5,询问区间[2; 4] 的魔法效果。区间[2; 4] 包含的连续子序列为‘‘1”; ‘‘2”; ‘‘4”; ‘‘1; 2”; ‘‘2; 4”; ‘‘1; 2; 4”, 它们的魔法值分别为1; 2; 4; 3; 6; 7,所以区间[2,4] 的魔法效果为1 + 2 + 4 + 3 + 6 + 7 = 23。
库洛牌的魔法效果狂拽炫酷吊炸天,这个值可能很大,所以你只需要输出这个值模100,000,007。另外,任性的君君可以在询问的过程中对库洛牌的魔法值进行修改。
现在,君君给出了M 个操作,操作格式如下:
1. M p x 表示将第p 张库洛牌的魔法值修改为x。
2. Q l r 表示询问区间[l; r] 的魔法效果。
Pascal 语言中,异或操作符为xor,C++ 语言中,异或操作符为^。

Input

第一行为一个整数N,表示有N 张库洛牌。
第二行为N 个整数,表示一开始N 张库洛牌的值。
第三行为一个整数M,表示有M 个操作。
接下来M 行,每行表示一个操作,格式如题目描述所示。

Output

对于每个操作2,输出一行,每行一个数,表示询问的区间[l,r] 的魔法效果模100,000,007。

Sample Input

5
1 2 3 4 5
7
Q 1 3
M 2 7
Q 1 3
M 2 2
Q 1 3
M 4 2
Q 1 5

Sample Output

10
26
10
47

Data Constraint

30% 的数据:N,M<=300
另外20% 的数据:N,M<=30000, 操作1 的数量不超过50
80% 的数据:N,M<=30000
100% 的数据:N<=100000;M<=100000; 0<=ai, x<=1000

分析:

符合线段树的标准特征:动态地问你答案。

但是仔细看后我们会发现无从下手,因为没有办法合并区间。

由于ai,x<=1000a_i,x,我们会发现转成二进制以后最多只有十位,那我们就打十棵线段树吧!

考虑怎么合并:
我们把一段区间[x..y][x..y]分成[x..m][x..m]和[m+1..y][m+1..y],那么[x..y][x..y]的所有连续子区间异或和就等于[x..m][x..m]的所有连续子区间异或和加上[m+1]..y[m+1]..y的所有连续子区间异或和再加上穿过这两个区间的所有的连续子区间异或和。

那么问题的关键就在于如何求穿过两个区间的所有连续子区间和。

这时候需要想到异或的性质。

当1的个数为奇数时,异或出来的结果是1。当1的个数是偶数时,异或出来的结果是0。

我们在维护一段区间的所有的连续的子区间异或和的同时,多维护5个值,分别是该区间内1的个数的奇偶性,前缀异或和等于0,1的个数,后缀异或和等于0,1的个数。

那么穿过两个区间异或和为1的子区间的个数=[x..m][x..m]后缀异或和等于0的个数×[m+1..y][m+1..y]前缀异或和等于1的个数+[x..m][x..m]后缀异或和等于1的个数×[m+1..y][m+1..y]前缀异或和等于0的个数。

至于怎么维护区间内前后缀异或和等于0,1的个数就用的到之前说要维护的1的个数的奇偶性了,请读者自行思考。

Code(pascal):

const rp=400005;
type arr=array[1..4] of int64;
vari,j,k,n,m:longint;ans,x,y:int64;d:array[1..10,1..rp,1..4] of int64;op:array[1..100000] of int64;m2:array[0..10] of int64;c:char;
procedure built;
beginm2[0]:=1;for i:=1 to 10 do m2[i]:=m2[i-1]*2;
end;
procedure maketree(t,i,x,y:int64);
var m:int64;
beginif x=y thenbegind[t,i,1]:=op[x] and m2[t-1] shr (t-1);d[t,i,2]:=d[t,i,1]; d[t,i,3]:=d[t,i,1]; d[t,i,4]:=d[t,i,1];end elsebeginm:=(x+y) div 2;maketree(t,i+i,x,m); maketree(t,i+i+1,m+1,y);d[t,i,1]:=d[t,i+i,1]+d[t,i+i+1,1]+d[t,i+i,3]*((y-m)-d[t,i+i+1,2])+((m-x+1)-d[t,i+i,3])*d[t,i+i+1,2];if d[t,i+i,4]=0 thenbegind[t,i,2]:=d[t,i+i+1,2]+d[t,i+i,2];end elsebegind[t,i,2]:=(y-m)-d[t,i+i+1,2]+d[t,i+i,2];end;if d[t,i+i+1,4]=1 thenbegind[t,i,3]:=(m-x+1)-d[t,i+i,3]+d[t,i+i+1,3];end elsebegind[t,i,3]:=d[t,i+i,3]+d[t,i+i+1,3];end;d[t,i,4]:=(d[t,i+i,4]+d[t,i+i+1,4]) mod 2;end;
end;
procedure change(t,i,x,y,l,r:int64);
var m:int64;
beginif (x=l)and(y=l) thenbegind[t,i,1]:=r and m2[t-1] shr (t-1);d[t,i,2]:=d[t,i,1]; d[t,i,3]:=d[t,i,1]; d[t,i,4]:=d[t,i,1];end elsebeginm:=(x+y) div 2;if l<=m then change(t,i+i,x,m,l,r) else change(t,i+i+1,m+1,y,l,r);d[t,i,1]:=d[t,i+i,1]+d[t,i+i+1,1]+d[t,i+i,3]*((y-m)-d[t,i+i+1,2])+((m-x+1)-d[t,i+i,3])*d[t,i+i+1,2];if d[t,i+i,4]=0 thenbegind[t,i,2]:=d[t,i+i+1,2]+d[t,i+i,2];end elsebegind[t,i,2]:=(y-m)-d[t,i+i+1,2]+d[t,i+i,2];end;if d[t,i+i+1,4]=1 thenbegind[t,i,3]:=(m-x+1)-d[t,i+i,3]+d[t,i+i+1,3];end elsebegind[t,i,3]:=d[t,i+i,3]+d[t,i+i+1,3];end;d[t,i,4]:=(d[t,i+i,4]+d[t,i+i+1,4]) mod 2;end;
end;
function find(t,i,x,y,l,r:int64):arr;
varm:int64;p,q:arr;
beginif (x=l)and(y=r) thenbeginfind:=d[t,i];end elsebeginm:=(x+y) div 2;if (r<=m) thenbeginfind:=find(t,i+i,x,m,l,r);end elsebeginif (l>m) thenbeginfind:=find(t,i+i+1,m+1,y,l,r);end elsebeginp:=find(t,i+i,x,m,l,m);q:=find(t,i+i+1,m+1,y,m+1,r);find[1]:=p[1]+q[1]+p[3]*((r-m)-q[2])+q[2]*((m-l+1)-p[3]);if p[4]=0 thenbeginfind[2]:=q[2]+p[2];end elsebeginfind[2]:=(r-m)-q[2]+p[2];end;if q[4]=1 thenbeginfind[3]:=(m-l+1)-p[3]+q[3];end elsebeginfind[3]:=p[3]+q[3];end;find[4]:=(p[4]+q[4]) mod 2;end;end;end;
end;
beginbuilt;readln(n);for i:=1 to n do read(op[i]);for i:=1 to 10 domaketree(i,1,1,n);readln(m);for i:=1 to m dobeginreadln(c,x,y);if c='M' thenbeginfor j:=1 to 10 dochange(j,1,1,n,x,y);end elsebeginans:=0;for j:=1 to 10 doans:=(ans+find(j,1,1,n,x,y)[1]*m2[j-1]) mod 100000007;writeln(ans);end;end;
end.

此法只能拿80分,因为常数太大。

0,1的个数可以只维护一个,这样常数会变小,还是比较危险(会打zkw非递归线段树的神牛勿喷)。

至于最好的做法,我们需要维护的是异或前缀和数组,这样修改就改成了区间修改,可是常数比较玄学,跑得非常快。

Code(pascal):

constrp=800010;
vard:array[1..10,1..rp] of int64;b:array[1..10,1..rp] of int64;op,oc:array[0..100000] of int64;m2:array[0..9] of int64;n,m,i,j:longint;ans,k,x,y,l:int64;c:char;
procedure maketree(t,i,x,y:int64);
var m:int64;
beginif x=y thenbegind[t,i]:=oc[x] and m2[t-1] shr (t-1);end elsebeginm:=(x+y) div 2;maketree(t,i+i,x,m); maketree(t,i+i+1,m+1,y);d[t,i]:=d[t,i+i]+d[t,i+i+1];end;
end;
procedure change(t,i,x,y,l,r:int64);
var m:int64;
beginif (x=l)and(y=r) thenbegind[t,i]:=(y-x+1)-d[t,i];b[t,i]:=1-b[t,i];end elsebeginm:=(x+y) div 2;if b[t,i]=1 thenbegind[t,i+i]:=(m-x+1)-d[t,i+i]; d[t,i+i+1]:=(y-m)-d[t,i+i+1];b[t,i+i]:=1-b[t,i+i]; b[t,i+i+1]:=1-b[t,i+i+1];b[t,i]:=0;end;if r<=m thenbeginchange(t,i+i,x,m,l,r);d[t,i]:=d[t,i+i]+d[t,i+i+1];exit;end;if l>m thenbeginchange(t,i+i+1,m+1,y,l,r);d[t,i]:=d[t,i+i]+d[t,i+i+1];exit;end;change(t,i+i,x,m,l,m); change(t,i+i+1,m+1,y,m+1,r);d[t,i]:=d[t,i+i]+d[t,i+i+1];end;
end;
function find(t,i,x,y,l,r:int64):int64;
var m:int64;
beginif (x=l)and(y=r) then exit(d[t,i]);m:=(x+y) div 2;if b[t,i]=1 thenbegind[t,i+i]:=(m-x+1)-d[t,i+i]; d[t,i+i+1]:=(y-m)-d[t,i+i+1];b[t,i+i]:=1-b[t,i+i]; b[t,i+i+1]:=1-b[t,i+i+1];b[t,i]:=0;end;if r<=m then exit(find(t,i+i,x,m,l,r));if l>m then exit(find(t,i+i+1,m+1,y,l,r));exit(find(t,i+i,x,m,l,m)+find(t,i+i+1,m+1,y,m+1,r));
end;
beginm2[0]:=1; for i:=1 to 9 do m2[i]:=m2[i-1]*2;readln(n);for i:=1 to n dobeginread(op[i]);oc[i]:=op[i] xor oc[i-1];end;for i:=1 to 10 do maketree(i,1,1,n);readln(m);for i:=1 to m dobeginreadln(c,x,y);if c='M' thenbeginfor j:=1 to 10 doif (y and m2[j-1] shr (j-1)) xor (op[x] and m2[j-1] shr (j-1))=1 thenbeginchange(j,1,1,n,x,n);end;op[x]:=y;end elsebeginans:=0;for j:=1 to 10 dobeginif x>1 then k:=find(j,1,1,n,x-1,y) else k:=find(j,1,1,n,1,y);l:=y-x-k+2;ans:=(ans+l*k*m2[j-1]) mod 100000007;end;writeln(ans);end;end;
end.

GDKOI 2016 魔卡少女相关推荐

  1. GDKOI2016 Day 1 T1 魔卡少女

    T1 魔卡少女 给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和. 线段树,对于二进制的每一位开一颗线段树.对于每一个区间,维护其从左 ...

  2. [GDKOI2016]魔卡少女

    题目描述 君君是中山大学的四年级学生.有一天在家不小心开启了放置在爸爸书房中的一本古书.于是,君君把放在书中最上面的一张牌拿出来观摩了一下,突然掀起一阵大风把书中的其她所有牌吹散到各地.这时一只看上去 ...

  3. GDKOI2016 魔卡少女

    题目 给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和.n,m<=100000,ai<=1000 分析 当时我可是直接暴力 ...

  4. GDKOI 2016

    GDKOI 2016 day 1 第一题 魔卡少女 题目描述:维护一个序列,能进行以下两个操作:1.将某一个位置的值改变.2.求区间的连续子串的异或值的和. solution 因为序列的数的值都小于\ ...

  5. 如何使用CocoStudio场景编辑器制作魔卡幻想

    1 CocoStudio 场景编辑器 使用 CocoStudio 场景编辑器来创建游戏场景,其中包含游戏 UI 与动画,来定制一个游戏主界面. 2 使用 CocoStudio 完成<魔卡幻想&g ...

  6. 程序员如何从技术上“开挂”魔卡手游? | 技术头条

    作者 | 孙景卫 责编 | 郭   芮 如何在短时间内成为Python工程师? https://edu.csdn.net/topic/python115?utm_source=csdn_bw 最近流行 ...

  7. 小苹果软件_游戏拼音魔卡动画教学软件使用说明书

    尊敬的老师.家长们:您们好! 随着抗击新冠病毒战疫的深入,政府要求大家继续留在家里"不出门,勤洗手,多喝水",孩子们在家怎么做到"停课不停学"呢? <游戏 ...

  8. 【cocos2d-x】如何使用CocoStudio场景编辑器制作魔卡幻想

    1 CocoStudio 场景编辑器 使用 CocoStudio 场景编辑器来创建游戏场景,其中包含游戏 UI 与动画,来定制一个游戏主界面. 2 使用 CocoStudio 完成<魔卡幻想&g ...

  9. 慕和副总裁隋成钢:手游大作《魔卡幻想》为何移植HTML5

    为期两天的第十一届TFC全球移动游戏大会已经圆满闭幕,知名手游<魔卡幻想>研发商慕和网络副总裁隋成钢应邀出席了9月11日的HTML5专场"TFC&LAYABOX大型HTM ...

最新文章

  1. 二进制搭建kubernetes多master集群【三、配置k8s master及高可用】
  2. 三维动画制作的基本流程
  3. 数据结构(5) -- 图
  4. linux gz 解压缩
  5. linux中tree命令
  6. .NET 6 HotReload的试用
  7. 看完少年的你,想到少年的我
  8. java excutorthread_JAVA 线程池ThreadPoolExcutor原理探究
  9. iLogtail使用入门-iLogtail本地配置模式部署(For Kafka Flusher)
  10. 有关LinkedList常用方法的源码解析
  11. oracle动态语句打开游标,Oracle动态语句中返回游标
  12. Mysql Server8.0下载安装配置环境教程
  13. 小程序毕设作品之微信酒店预订小程序毕业设计(1)开发概要
  14. AD14简明使用教程(同样试用于手工制板)
  15. bzoj4391 [Usaco2015 dec]High Card Low Card题解
  16. python语言例子_第一个Python实例
  17. 合并的表格怎么加横线_word
  18. Zlib 1.2.11 Windows 编译
  19. SVN如何对已经提交的注释进行再次修改?
  20. Python爬虫之小试牛刀——使用Python抓取百度街景图像

热门文章

  1. mt4查看虚拟服务器,mt4 如何查看服务器地址
  2. VSCode查看和编辑远程服务器的代码
  3. 学习HTML5 Canvas这一篇文章就够了
  4. 如何从零开始搭建一个网站
  5. Nginx(三):日志
  6. 中软国际首届嘉年华晚会 创新网络年会PK“春晚”
  7. Job Statement
  8. 生活中的数学问题(数学家的难题)
  9. 曹雪芹诗歌中的鸿蒙,曹雪芹的诗词丢失,红楼梦里的诗句
  10. 2019上半年恶意挖矿趋势报告