【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\)个元素的 ...
随机推荐
- 选择器zuoye
代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title ...
- 判断MDI窗体的子窗体是否存在
//***************************************************************************//函 数名: CreateForm//返 回 ...
- 学习servlet之路--javax-servlet不存在
我在编译一个servlet菜鸟教程下提供的包含有javax.servlet包的java文件,变异出错, import java.io.*;import javax.servlet.*;import j ...
- JSF(JavaServer Faces)简介
JavaServer Faces (JSF) 是一种用于构建Java Web 应用程序的标准框架(是Java Community Process 规定的JSR-127标准).它提供了一种以组件为中心的 ...
- os.path.dirname(__file__)使用、Python os.path.abspath(__file__)使用
python中的os.path.dirname(__file__)的使用 - CSDN博客https://blog.csdn.net/u011760056/article/details/469698 ...
- PAT甲级——A1137 Final Grading【25】
For a student taking the online course "Data Structures" on China University MOOC (http:// ...
- Office2016只安装三件套方法
转载 Office2016只安装三件套方法(word,ppt,excel) 2019-03-01 23:30:03 Kellen5l 阅读数 11618更多 分类专栏: Office 版权声明:本 ...
- 【默默努力】h5-game-heroVSmonster
先放下作者大大的项目地址:https://github.com/yangyunhe369/h5-game-heroVSmonster 然后游戏的效果为 截动图的按键与游戏按键应该冲突,我就截几张图片了 ...
- 在vue项目中使用Nprogress.js进度条
NProgress是一款在网页顶部添加细长进度条的工具,非常轻巧,使用起来也非常便捷,灵感来源于Google, YouTube. 1.安装 $ npm install --save nprogress ...
- windows pip 安装 转载
经常在使用Python的时候需要安装各种模块,而pip是很强大的模块安装工具,但是由于国外官方pypi经常被墙,导致不可用,所以我们最好是将自己使用的pip源更换一下,这样就能解决被墙导致的装不上库的 ...