【NOIP2018模拟11.01】树
题目
描述
题目大意
维护一个序列,支持三种操作:
1、修改一段区间,将这段区间内的所有数都andandand一个数。
2、询问区间和。
3、询问区间两两相加的平方和。
N≤10000N\leq 10000N≤10000
思路
显然是一道数据结构题。
毋庸置疑的,这绝对是一棵线段树。
第三个操作还是比较简单的:
∑(ai+aj)2=∑ai2+aj2+2aiaj=2∗len∗∑ai2+2∑aiaj=2∗len∗∑ai2+2(∑ai)2\sum{(a_i+a_j)^2} \\
=\sum{a_i^2+a_j^2+2a_ia_j}\\
=2*len*\sum{a_i^2}+2\sum{a_ia_j}\\
=2*len*\sum{a_i^2}+2\left(\sum{a_i}\right)^2∑(ai+aj)2=∑ai2+aj2+2aiaj=2∗len∗∑ai2+2∑aiaj=2∗len∗∑ai2+2(∑ai)2
所以只需要维护区间和还有区间平方和。
这题中,最讨厌的就是修改操作,好端端的,干嘛要来个位运算!
所以我就是着将所有的位分开来。
然而,搞不了第三个询问……
想了半天后弃疗看题解。
正解
这题正解就是直接暴力,没错,就是暴力。
对于线段树的每一个节点,维护一个值表示这段区间内或起来的和。
在修改的时候,我们就可以通过这个东西来判断这个区间里面是否有需要修改的数。
如果有,就继续往下,将它揪出来,暴力修改。
然后?然后就没了啊……
听起来这个方法的时间很诡异,实际上——
对于NNN个点,每个点一共有303030个位,又因为修改过一个位之后就再也不可能修改这个位,所以,顶多修改30N30N30N次。
乘上线段树的高度就是30NlgN30N\lg N30NlgN次。
所以时间复杂度是O(NlgNlg109)O(N\lg N\lg 10^9)O(NlgNlg109)
代码
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100000
#define BIt 30
#define mo 998244353
inline long long pow2(long long x){return x*x;}
int n;
int a[N+1];
struct Ret{//分别是区间和、区间平方和
long long sum;
int sum2;
};
struct Node{
int o;//表示or值
Ret s;
} d[N*4+1];
void init(int,int,int);
void find(int,int,int,int,int,int);//找被修改区间完全覆盖的点
void change(int,int,int,int);
inline Ret operator+(const Ret &a,const Ret &b){
return {a.sum+b.sum,(a.sum2+b.sum2)%mo};
}
Ret query(int,int,int,int,int);
int main(){
freopen("seg.in","r",stdin);
freopen("seg.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
init(1,1,n);
int T;
scanf("%d",&T);
while (T--){
int op;
scanf("%d",&op);
if (op==1){
int l,r,x;
scanf("%d%d%d",&l,&r,&x);
find(1,1,n,l,r,x);
}
else if (op==2){
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",query(1,1,n,l,r).sum);
}
else{
int l,r;
scanf("%d%d",&l,&r);
Ret res=query(1,1,n,l,r);
printf("%lld\n",(((long long)res.sum2*(r-l+1)%mo+pow2(res.sum%mo)%mo)<<1)%mo);
}
}
return 0;
}
void init(int k,int l,int r){
if (l==r){
d[k].s.sum=d[k].o=a[l];
d[k].s.sum2=(long long)a[l]*a[l]%mo;
return;
}
int mid=l+r>>1;
init(k<<1,l,mid);
init(k<<1|1,mid+1,r);
d[k].o=d[k<<1].o|d[k<<1|1].o;
d[k].s=d[k<<1].s+d[k<<1|1].s;
}
void find(int k,int l,int r,int st,int en,int x){
if (st<=l && r<=en){
change(k,l,r,x);
return;
}
int mid=l+r>>1;
if (st<=mid)
find(k<<1,l,mid,st,en,x);
if (mid<en)
find(k<<1|1,mid+1,r,st,en,x);
d[k].o=d[k<<1].o|d[k<<1|1].o;
d[k].s=d[k<<1].s+d[k<<1|1].s;
}
void change(int k,int l,int r,int x){
if ((d[k].o&x)==d[k].o)
return;
if (l==r){
d[k].s.sum=d[k].o&=x;
d[k].s.sum2=(long long)d[k].o*d[k].o%mo;
return;
}
int mid=l+r>>1;
change(k<<1,l,mid,x);
change(k<<1|1,mid+1,r,x);
d[k].o=d[k<<1].o|d[k<<1|1].o;
d[k].s=d[k<<1].s+d[k<<1|1].s;
}
Ret query(int k,int l,int r,int st,int en){
if (st<=l && r<=en)
return d[k].s;
int mid=l+r>>1;
Ret res={0,0};
if (st<=mid)
res=res+query(k<<1,l,mid,st,en);
if (mid<en)
res=res+query(k<<1|1,mid+1,r,st,en);
return res;
}
总结
数据结构的时间复杂度,不应该只看他每次操作的复杂度,还要看看总共最多的复杂度。尤其是类似一次性修改的东西(就是这个数据修改过一次之后就不能再修改了)。
话说,我突然想起以前的一道题目:
有一道数据结构提,正解是分块的根号做法,题解说,线段树不能做……
我坚持用线段树,最终AC了那题,log做法,吊打标算。风光了一时
当时用的也差不多是这样的思想……
【NOIP2018模拟11.01】树的更多相关文章
- 【NOIP2019模拟11.01】Game(贪心+线段树)
Description: 小 A 和小 B 在玩一个游戏,他们两个人每人有
- [jzoj NOIP2018模拟11.02]
嗯T1忘记取模了,100到20 嗯T2忘记了那啥定理,暴力也写炸了,这题我认 嗯T3线段树合并分裂没有写炸,考场上就知道妥妥的70分.但是,分数出的时候听到有人说暴力也是70分,我???脸黑,枉我敲了 ...
- 6402. 【NOIP2019模拟11.01】Cover(启发式合并)
题目描述 Description 小 A 现在想用
- 17.10.31&11.01
10.31模拟考试 Prob.1(AC)裸的矩阵幂 Prob.2(WA)(类似括号匹配求合法方案数) 卡特兰数的一个模型运用.可以推出一个式子(推导方法一个erge讲的,一个骚猪讲的) Prob.3( ...
- 8.1 NOIP模拟11
8.1 NOIP模拟 11 今天上午返校之后,颓了一会,然后下午就开始考试,中午睡着了,然后刚开始考试的时候就困的一匹,我一看T1,woc,这不是之前线段树专题的题啊,和那道题差不多,所以我..... ...
- [NOIP2018模拟赛10.16]手残报告
[NOIP2018模拟赛10.16]手残报告 闲扯 炉石乱斗模式美滋滋啊,又颓到好晚... 上来T2先敲了树剖,看T1发现是个思博DP,然后没过大样例,写个暴力发现还是没过大样例!?才发现理解错题意了 ...
- JZOJ 4298. 【NOIP2015模拟11.2晚】我的天
4298. [NOIP2015模拟11.2晚]我的天 (File IO): input:ohmygod.in output:ohmygod.out Time Limits: 1000 ms Memor ...
- JZOJ 3929. 【NOIP2014模拟11.6】创世纪
3929. [NOIP2014模拟11.6]创世纪 (Standard IO) Time Limits: 1000 ms Memory Limits: 65536 KB Description 上帝手 ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T2 Lucas的数列
[NOIP2015模拟11.5]JZOJ8月5日提高组T2 Lucas的数列 题目 PS:\(n*n*T*T<=10^{18}\)而不是\(10^1*8\) 题解 题意: 给出\(n\)个元素的 ...
随机推荐
- leetcode-90-子集②
题目描述: 方法一:回溯 class Solution: def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: nums.s ...
- Oracle大数据SQL语句优化
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...
- 阿里云在云栖大会发布SaaS加速器3.0版最新成果,让天下没有难做的SaaS
2019年杭州·云栖大会顺利落幕,超过6万人次观展,200余位顶尖科学家分享了前沿技术.作为“阿里云不做SaaS”,坚持“被集成”战略的落地体现,阿里云SaaS加速器在云栖大会现场发布了SaaS加速器 ...
- mac idea解决快捷键的问题
取消mac的快捷键 设置->键盘->快捷键 我这里取消的有:聚焦->显示聚焦搜索 应用快捷键->显示帮助菜单. 类似eclipse的自动提示错误的解决方案(quick fix ...
- django零散知识点
后端将对象以对象形式传到前端: from django.core.serializers import serialize def xxx(reqeust): project_list = model ...
- c#使用打印机
在windows应用程序中文档的打印是一项非常重要的功能,在以前一直是一个非常复杂的工作,Microsoft .net Framework的打印功能都以组件的方式提供,为程序员提供了很大的方便,但是这 ...
- java关于lombok(包括父类参数)
java关于lombok对bean对象进行自动设置 使用说明 使用方式 注释类型 @NonNull @Data(常用) @NoArgsConstructor(常用)/@RequiredArgsCons ...
- UBOOT把文件写入 NandFlash
如果把一个传到内存中的文件写入到 Nand Flash 中, 如:新的 uboot.bin, zImage(内核), rootfs 等, 如果做呢?我们可以用 Nand Flash 命令来完成. 但是 ...
- Python基础知识之4——三大控制结构
控制结构就是控制程序执行顺序的结构. Python 有三大控制结构,分别是顺序结构.分支结构(选择结构)以及循环结构.任何一个项目或者算法都可以使用这三种结构来设计完成.这三种控制结构也是结构化程序 ...
- NuGet 命令行使用EntityFrameWork
初始化 Enable-migrations 迁移 Add-Migration Donator_Add_CreationTime 执行操作 UpDate-database 撤销更改 Update-Dat ...
