【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\)个元素的 ...
随机推荐
- 【JZOJ6293】迷宫
description analysis 有没有想起[\(NOIP2018\)]保卫王国? 设\(tr[t][x][y]\)表示线段树上的\(t\)节点代表的区间,从最左边列的\(x\)行到最右边列\ ...
- C++仿函数和回调函数的异同
C++回调函数(callback)与仿函数(functor)的异同 c++仿函数 functor C++仿函数和回调函数的异同
- js 盒子模型与盒子偏移量
js 盒子模型: 通过js中提供的一系列属性和方法获取页面中元素的样式信息值. 一.client系类—>只读属性不可设置 (当前元素的私有属性,和内容溢出没关系,如果给容器设置了高度,就采用设置 ...
- (34)C#异常
一.异常的层次结构 二.异常格式 异常的一般格式 try { //可能会抛出异常的代码 } catch { //发现错误后会运行这里面的代码 } finally { //写不论是否出现异常都执行的代码 ...
- elasticsearch的索引清理
curl -XDELETE 'http://127.0.0.1:9200/winlogbeat-6.0.0-2017.07.*' 脚本加api删除(推荐) cat es-index-clear.sh ...
- Python3简介
Python3简介 Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. Python 的设计具有很强的可读性,相比其他语言经常使用英文关键字,其他语言的一些标点符号,它具有 ...
- PKU Campus 2015
PKU Campus 2015 B 注意到竖着落下不改变列模 4 的结果.问题转化为:模 4 系下,给序列,可选长度为 4 子区间,区间加一,能否让所有元素相等. C.Rabbit's Festiva ...
- DIV常用属性大全自己整理
一.属性列表 代码如下: color : #999999 文字颜色 font-family : 宋体 文字字型 font-size : 10pt 文字大小 font-style:itelic 文字斜体 ...
- 批量处理数据 SqlBulkCopy
string connectionString = new PublicDBHelper().GetCon(System.Configuration.ConfigurationManager.AppS ...
- COGITATE | 分析当前热门软件的创新
热门软件分析实例一——Github [简介] gitHub是一个面向开源及私有软件项目的托管平台,因为只支持git 作为唯一的版本库格式进行托管,故名gitHub.作为一个分布式的版本控制系统,在Gi ...