[ABC265G] 012 Inversion
Problem Statement
You are given a sequence $A=(A_1,\ldots,A_N)$ of length $N$. Each element is $0$, $1$, or $2$.
Process $Q$ queries in order. Each query is of one of the following kinds:
1 L R: print the inversion number of the sequence $(A_L,\ldots,A_R)$.2 L R S T U: for each $i$ such that $L\leq i \leq R$, if $A_i$ is $0$, replace it with $S$; if $A_i$ is $1$, replace it with $T$; if $A_i$ is $2$, replace it with $U$.
What is the inversion number?
The inversion number of a sequence $B = (B_1, \ldots, B_M)$ is the number of pairs of integers $(i, j)$ $(1 \leq i < j \leq M)$ such that $B_i > B_j$.
Constraints
- $1 \leq N \leq 10^5$
- $0 \leq A_i \leq 2$
- $1\leq Q\leq 10^5$
- In each query, $1\leq L \leq R \leq N$.
- In each query of the second kind, $0\leq S,T,U \leq 2$.
- All values in input are integers.
Input
Input is given from Standard Input in the following format:
$N$ $Q$
$A_1$ $A_2$ $\ldots$ $A_N$
$\rm Query_1$
$\rm Query_2$
$\vdots$
$\rm Query_Q$
$\rm Query_i$ denotes the $i$-th query, which is in one of the following formats:
$1$ $L$ $R$
$2$ $L$ $R$ $S$ $T$ $U$
Output
Print the responses to the queries of the first kind in the given order, separated by newlines.
Sample Input 1
5 3
2 0 2 1 0
1 2 5
2 2 4 2 1 0
1 2 5
Sample Output 1
3
4
Initially, $A=(2,0,2,1,0)$.
- In the $1$-st query, print the inversion number $3$ of $(A_2,A_3,A_4,A_5)=(0,2,1,0)$.
- The $2$-nd query makes $A=(2,2,0,1,0)$.
- In the $3$-rd query, print the inversion number $4$ of $(A_2,A_3,A_4,A_5)=(2,0,1,0)$.
Sample Input 2
3 3
0 1 2
1 1 1
2 1 3 0 0 0
1 1 3
Sample Output 2
0
0
区间修改区间询问,首先考虑线段树。
那么我们可以把一对逆序对分成两类,把线段用线段树分成一个个区间后,逆序对有些两个数在一个区间里,有些不在一个区间里。在一个区间里的逆序对,我们可以每次更新的时候都维护逆序对个数。而不再一个区间里的,我们可以在外面再跑一次
那么具体来说。首先不考虑修改,一个区间的逆序对数量需要分开来记录才好记录。记录 \(p_{i,j}\) 为这个区间中形如 \((i,j)\) 的有序数对有多少个。当然我们还要记录一个区间有多少个0,多少个1,多少个2.
线段树上两个区间合并时,节点 \(o\) 的有序数对 \((i,j)\) 的数量为左儿子 \((i,j)\) 的数量和右儿子 \((i,j)\) 的数量加上左区间 \(i\) 的数量和右区间 \(j\) 的数量之积。
区间修改自然还要打tag,记录这个区间中原有的 0 变成那个数字,1变成那个数字,2变成那个数字。这个 tag 也很好合并,更新时逐个数字更新就好了。
线段树的部分解决了,来看询问时的部分。询问时对于跨过区间的逆序对,我们可以记录在这个区间前面有多少个 0,有多少个 1,有多少个2,然后乘起来加上就好。
#include<bits/stdc++.h>
const int N=1e5+5;
typedef long long LL;
struct node{
int a[3],s,t,u;
LL b[3][3];
}tr[N<<2];
LL ret;
int n,op,l,r,s,t,u,q,x,a0,a1,a2;
void pushup(int o)
{
for(int i=0;i<3;i++)
tr[o].a[i]=tr[o<<1].a[i]+tr[o<<1|1].a[i];
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
tr[o].b[i][j]=tr[o<<1].b[i][j]+tr[o<<1|1].b[i][j]+1LL*tr[o<<1].a[i]*tr[o<<1|1].a[j];
}
void turn(int o,int s,int t,int u)
{
int a[3],p[3];
LL b[3][3];
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
p[0]=s,p[1]=t,p[2]=u;
for(int i=0;i<3;i++)
{
a[p[i]]+=tr[o].a[i];
for(int j=0;j<3;j++)
b[p[i]][p[j]]+=tr[o].b[i][j];
}
memcpy(tr[o].a,a,sizeof(a));
memcpy(tr[o].b,b,sizeof(b));
}
void add(int o,int s,int t,int u)
{
if(tr[o].s==-1)
tr[o].s=s,tr[o].t=t,tr[o].u=u;
else
{
int p[3]={s,t,u};
tr[o].s=p[tr[o].s];
tr[o].t=p[tr[o].t];
tr[o].u=p[tr[o].u];
}
}
void pushdown(int o)
{
if(tr[o].s!=-1)
{
turn(o<<1,tr[o].s,tr[o].t,tr[o].u);
turn(o<<1|1,tr[o].s,tr[o].t,tr[o].u);
add(o<<1,tr[o].s,tr[o].t,tr[o].u);
add(o<<1|1,tr[o].s,tr[o].t,tr[o].u);
tr[o].s=tr[o].t=tr[o].u=-1;
}
}
void solve(int o,int l,int r)
{
if(l>r)
return;
if(l==r)
{
scanf("%d",&x);
tr[o].a[x]++;
return;
}
int md=l+r>>1;
solve(o<<1,l,md);
solve(o<<1|1,md+1,r);
pushup(o);
tr[o].s=tr[o].t=tr[o].u=-1;
}
LL query(int o,int l,int r,int x,int y)
{
if(x<=l&&r<=y)
{
ret+=1LL*a2*tr[o].a[1];
ret+=1LL*a1*tr[o].a[0];
ret+=1LL*a2*tr[o].a[0];
a0+=tr[o].a[0];
a1+=tr[o].a[1];
a2+=tr[o].a[2];
return tr[o].b[2][1]+tr[o].b[2][0]+tr[o].b[1][0];
}
pushdown(o);
int md=l+r>>1;
LL ret=0;
if(md>=x)
ret+=query(o<<1,l,md,x,y);
if(md<y)
ret+=query(o<<1|1,md+1,r,x,y);
return ret;
}
void update(int o,int l,int r,int x,int y,int s,int t,int u)
{
if(x<=l&&r<=y)
{
turn(o,s,t,u);
add(o,s,t,u);
return;
}
pushdown(o);
int md=l+r>>1;
if(md>=x)
update(o<<1,l,md,x,y,s,t,u);
if(md<y)
update(o<<1|1,md+1,r,x,y,s,t,u);
pushup(o);
}
int main()
{
scanf("%d%d",&n,&q);
solve(1,1,n);
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&l,&r),ret=a0=a1=a2=0;
printf("%lld\n",query(1,1,n,l,r)+ret);
}
else
{
scanf("%d%d%d%d%d",&l,&r,&s,&t,&u);
update(1,1,n,l,r,s,t,u);
}
}
}
[ABC265G] 012 Inversion的更多相关文章
- HDU 1394 Minimum Inversion Number ( 树状数组求逆序数 )
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 Minimum Inversion Number ...
- 控制反转Inversion of Control (IoC) 与 依赖注入Dependency Injection (DI)
控制反转和依赖注入 控制反转和依赖注入是两个密不可分的方法用来分离你应用程序中的依赖性.控制反转Inversion of Control (IoC) 意味着一个对象不会新创建一个对象并依赖着它来完成工 ...
- HDU 1394 Minimum Inversion Number(最小逆序数 线段树)
Minimum Inversion Number [题目链接]Minimum Inversion Number [题目类型]最小逆序数 线段树 &题意: 求一个数列经过n次变换得到的数列其中的 ...
- 依赖倒置原则(Dependency Inversion Principle)
很多软件工程师都多少在处理 "Bad Design"时有一些痛苦的经历.如果发现这些 "Bad Design" 的始作俑者就是我们自己时,那感觉就更糟糕了.那么 ...
- HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS Memory Limit: 32768 K Description The inve ...
- Inversion Sequence(csu 1555)
Description For sequence i1, i2, i3, … , iN, we set aj to be the number of members in the sequence w ...
- ACM: 强化训练-Inversion Sequence-线段树 or STL·vector
Inversion Sequence Time Limit:2000MS Memory Limit:262144KB 64bit IO Format:%lld & %llu D ...
- ACM Minimum Inversion Number 解题报告 -线段树
C - Minimum Inversion Number Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d &a ...
- HDU-Minimum Inversion Number(最小逆序数)
Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...
- 【hdu1394】Minimum Inversion Number
Problem Description The inversion number of a given number sequence a1, a2, ..., an is the number of ...
随机推荐
- 2、搭建MyBatis
2.1.开发环境 IDE:idea 2019.2 构建工具:maven 3.8.4 MySQL版本:MySQL 5.7 MyBatis版本:MyBatis 3.5.7 MySQL不同版本的注意事项 ( ...
- 质量管理 | QC、QA、QM,去QA化与降本增效
现在国内职业的质量管理都是从 CMMI 和 ISO 质量体系演化过来的,但是能做真正的质量管理的公司很少.质量管理的 QC 偏测试,对最终的产品负责:QA 偏过程,从过程把控质量:QM 偏体系,类似于 ...
- 【项目源码】基于JSP动漫论坛的设计与实现
动漫论坛项目主要用于实现动漫爱好者的互相交流,基本功能包括:注册用户.登录.浏览帖子.发布新帖.回复帖子.等.本系统结构如下: (1)普通用户: 注册用户:如果用户为非会员用户,通过注册,经审核通过之 ...
- HDLbits_Conwaylife
题目介绍 题目链接 Conwaylife 简介 题目要求我们实现一个康威生命游戏的电路. 该游戏在一个二维网格空间中进行,在该题目中是 16 * 16 的大小,每一个格子都有两种状态(0 或 1),代 ...
- MySQL篇:第一章_软件安装和基本操作
本篇安装软件Navicate Premium 16破解版和phpstudy_pro phpstudy_pro安装教程 phpstudy官网:https://www.xp.cn/download.htm ...
- KRPANO太阳光插件
KRPano太阳光插件可以在全景项目中添加太阳光特效,如下图所示: 同时,该插件支持可视化编辑 使用说明 1.下载插件,把插件放入skin文件夹里面 2.在tour.xml文件中,添加下面的插件引用 ...
- Kafka与RabbitMQ
一.什么是kafka,什么是rabbit Kafka是由Scala语言开发的一种分布式流处理框架,主要用于处理活跃的流式数据,以及大数据量的数据处理.它采用发布-订阅模型,支持消息的批量处理,数据 ...
- 「luogu - P4313」文理分科 Mincut
link. Pretty nice practice for the min-cut trick. Starting out we eliminate the constraint that if f ...
- mooc第四单元《管理团队》单元测试
第四单元<管理团队>单元测试 返回 本次得分为:6.00/10.00, 本次测试的提交时间为:2020-08-30, 如果你认为本次测试成绩不理想,你可以选择 再做一次 . 1 判断(2分 ...
- Java流程控制10道题_上机
Java流程控制10道题 计算出1-100之间所有不能被3整除的整数的和大于(或等于)2000的数字. package day01; public class Lab01 { public stati ...