题目链接:https://zhixincode.com/contest/22/problem/I?problem_id=314

样例输入 1

5 9 3
1 5 3 2 4
1 1 5
2 1 5
1 1 1
1 2 2
1 3 3
1 4 4
1 5 5
3 3 5
1 1 4

样例输出 1

15
1
3
2
5
4
13

题解:

dls出的题真好qwq!

我们先考虑partition的两种操作,若将所有小于等于 $x$ 的数字看成 $0$,将所有大于 $x$ 的数字看成 $1$,那么原序列就变成了一个 $01$ 序列。

那么两种partition操作,就相当于将某个区间内的所有 $0$ 放到一边,所有 $1$ 放到另一边。这个操作就很简单,我们可以 $O(\log n)$ 统计出该区间内有多少个 $0$ 以及多少个 $1$,然后相应的将区间的左边一段赋值成 $0$(或者 $1$),将区间右边一段赋值成 $1$(或者 $0$)。

然后,对于求和操作:

首先不难发现,不管怎么操作,对于所有小于等于 $x$ 的数字来说,它们之间的顺序是不会改变的;同样对于所有大于 $x$ 的数字,它们之间的顺序也不会改变。因此,对于任意一个位置,假设该位置上是一个 $0$,那么只要统计这个位置左侧有几个 $0$ 就可以知道,这个位置对应到原序列是什么数字。当然,我们若是对区间内每个位置都这样去求出是多少,再求和,显然时间复杂度是比较差的。

因此,我们可以根据前缀和的思想,对于要求和的区间 $[l,r]$,我们可以 $O(\log n)$ 统计出 $[1,l-1]$ 和 $[1,r]$ 各有多少个 $0$,然后我们就知道了 $[l,r]$ 区间对应到原序列是哪个区间,然后原序列做一下前缀和求差值即可得到答案。类似的,统计 $1$ 的数目也是这样一个道理。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+; int n,q,x,v[maxn];
int tota,totb;
ll a[maxn],b[maxn]; #define ls (rt<<1)
#define rs (rt<<1|1)
struct Node{
int l,r;
int val,lazy;
void update(int x)
{
val=(r-l+)*x;
lazy=x;
}
}o[maxn<<];
void pushdown(int rt)
{
if(o[rt].lazy==-) return;
o[ls].update(o[rt].lazy);
o[rs].update(o[rt].lazy);
o[rt].lazy=-;
}
inline void pushup(int rt)
{
o[rt].val=o[ls].val+o[rs].val;
}
void build(int rt,int l,int r)
{
o[rt].l=l, o[rt].r=r;
o[rt].lazy=-;
if(l==r)
{
o[rt].val=(v[l]>x);
return;
}
int mid=(l+r)>>;
build(ls,l,mid);
build(rs,mid+,r);
pushup(rt);
}
void update(int rt,int st,int ed,int val)
{
if(st<=o[rt].l && o[rt].r<=ed)
{
o[rt].update(val);
return;
}
pushdown(rt);
int mid=(o[rt].l+o[rt].r)>>;
if(st<=mid) update(ls,st,ed,val);
if(mid<ed) update(rs,st,ed,val);
pushup(rt);
}
int query(int rt,int st,int ed)
{
if(st>ed) return ;
if(st<=o[rt].l && o[rt].r<=ed) return o[rt].val;
pushdown(rt);
int mid=(o[rt].l+o[rt].r)>>, res=;
if(st<=mid) res+=query(ls,st,ed);
if(mid<ed) res+=query(rs,st,ed);
pushup(rt);
return res;
} int main()
{
ios::sync_with_stdio();
cin.tie(), cout.tie(); cin>>n>>q>>x; tota=totb=, a[]=b[]=;
for(int i=;i<=n;i++)
{
cin>>v[i]; //按x拆分序列并求前缀和
if(v[i]<=x) a[++tota]=a[tota-]+v[i];
if(v[i]>x) b[++totb]=b[totb-]+v[i];
} build(,,n);
while(q--)
{
int t,l,r; cin>>t>>l>>r;
if(t==)
{
int r_cnt1=query(,,r), r_cnt0=(r-+)-r_cnt1;
int l_cnt1=query(,,l-), l_cnt0=((l-)-+)-l_cnt1;
cout<<(a[r_cnt0]-a[l_cnt0])+(b[r_cnt1]-b[l_cnt1])<<'\n';
}
if(t==)
{
int cnt1=query(,l,r), cnt0=(r-l+)-cnt1;
update(,l,l+cnt0-,), update(,r-cnt1+,r,);
}
if(t==)
{
int cnt1=query(,l,r), cnt0=(r-l+)-cnt1;
update(,l,l+cnt1-,), update(,r-cnt0+,r,);
}
}
}

CCPC-Wannafly Winter Camp Day5 Div1 - Sorting - [线段树]的更多相关文章

  1. Wannafly Winter Camp Day5 Div1 E题 Fast Kronecker Transform 转化为NTT或FFT

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog @ Problem:传送门  原题目描述在最下面.  对给定的式子算解.   ...

  2. 2020 CCPC Wannafly Winter Camp Day1 C. 染色图

    2020 CCPC Wannafly Winter Camp Day1 C. 染色图 定义一张无向图 G=⟨V,E⟩ 是 k 可染色的当且仅当存在函数 f:V↦{1,2,⋯,k} 满足对于 G 中的任 ...

  3. Wannafly Winter Camp Day8(Div1,onsite) E题 Souls-like Game 线段树 矩阵乘法

    目录 Catalog Solution: (有任何问题欢迎留言或私聊 && 欢迎交流讨论哦 Catalog @ Problem:传送门  Portal  原题目描述在最下面.  简单的 ...

  4. CCPC Wannafly Winter Camp Div2 部分题解

    Day 1, Div 2, Prob. B - 吃豆豆 题目大意 wls有一个\(n\)行\(m\)列的棋盘,对于第\(i\)行第\(j\)列的格子,每过\(T[i][j]\)秒会在上面出现一个糖果, ...

  5. 2020 CCPC Wannafly Winter Camp Day1 Div.1&amp F

    #include<bits/stdc++.h> #define forn(i, n) for (int i = 0; i < int(n); i++) #define fore(i, ...

  6. 2020 CCPC Wannafly Winter Camp Day1 - I. K小数查询(分块)

    题目链接:K小数查询 题意:给你一个长度为$n$序列$A$,有$m$个操作,操作分为两种: 输入$x,y,c$,表示对$i\in[x,y] $,令$A_{i}=min(A_{i},c)$ 输入$x,y ...

  7. 2020 CCPC Wannafly Winter Camp Day2-K-破忒头的匿名信

    题目传送门 sol:先通过AC自动机构建字典,用$dp[i]$表示长串前$i$位的最小代价,若有一个单词$s$是长串的前$i$项的后缀,那么可以用$dp[i - len(s)] + val(s)$转移 ...

  8. 2020 CCPC Wannafly Winter Camp Day1-F-乘法

    题目传送门 sol:二分答案$K$,算大于$K$的乘积有多少个.关键在于怎么算这个个数,官方题解上给出的复杂度是$O(nlogn)$,那么计算个数的复杂度是$O(n)$的.感觉写着有点困难,自己写了一 ...

  9. Wannafly Winter Camp 2020 Day 7A 序列 - 树状数组

    给定一个全排列,对于它的每一个子序列 \(s[1..p]\),对于每一个 \(i \in [1,p-1]\),给 \(s[i],s[i+1]\) 间的每一个值对应的桶 \(+1\),求最终每个桶的值. ...

随机推荐

  1. Hadoop2.2.0分布式安装配置详解[2/3]

    前言 本文主要通过对hadoop2.2.0集群配置的过程加以梳理,所有的步骤都是通过自己实际测试.文档的结构也是根据自己的实际情况而定,同时也会加入自己在实际过程遇到的问题.搭建环境过程不重要,重要点 ...

  2. 阿里巴巴MySQL DBA面试题答案[转]

    无意中看到阿里巴巴的面试题,,借此回首DBMS时刻趁热打铁巩固一下基础 拿到题目大概浏览了一遍难度大概在中上游水平,自己跪了接近35%的题目 自己答题如下,欢迎大家讨论分析题 1 2 3 4 5 6 ...

  3. 微信支付(APP支付)-服务端开发(一)

    微信支付,首先需要注册一个商户平台公众账号,(网址:https://pay.weixin.qq.com/index.php/home/d_login) 目前微信支付的接入方式有四种方式:公众号支付,A ...

  4. Gitbook 命令行工具

    1.Gitbook 简介 1.1 Gitbook GitBook 是一个基于 Node.js 开发的命令行工具,使用它可以很方便的管理电子书,GitBook 是目前最流行的开源书籍写作方案. 使用 G ...

  5. mysql8.0.11修改root密码,其他创建用户和删除用户

    1.7. 查询用户密码: 查询用户密码命令:mysql> select host,user,authentication_string from mysql.user; host: 允许用户登录 ...

  6. Socket网络编程--网络爬虫(2)

    上一小节,我们实现了下载一个网页.接下来的一步就是使用提取有用的信息.如何提取呢?一个比较好用和常见的方法就是使用正则表达式来提取的.想一想我们要做个什么样的网络爬虫好呢?我记得以前好像博客园里面有人 ...

  7. 《深入应用C++11:代码优化与工程级应用》勘误表

    <深入应用C++11:代码优化与工程级应用>勘误表,会不断更新,欢迎读者留言或发邮件(cpp11book@163.com)给我提出宝贵意见. 1.第7.3节目录final和override ...

  8. 基于Docker的redis集群搭建

    Redis集群官方介绍:http://www.redis.cn/topics/cluster-tutorial.html 基于Docker搭建Redis集群 环境:6个节点,三主三从 制作Redis镜 ...

  9. java 实现websocket

    最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向 ...

  10. 【LINUX】——如何配置宿主机和虚拟机IP在同一网段

    宿主机:win7  10.8.2.50 255.255.255.0 虚拟机:redhat 如果使用 NAT 的网络连接方式,虚拟机的 IP 会被分配为 192.168.*.* 网段,从虚拟机 ping ...