[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 ...
随机推荐
- SpringBoot+Mybatis-Plus+Mysql的保姆级搭建
本文通过简单的示例代码和说明,让读者能够了解Mybatis-Plus+Mysql的简单使用 必须说明的是,本文有部分内容是为了后续的微服务写的,所以如果只想用Mybatis-Plus的话,直接使用ba ...
- Django模板(请用Django2.0版本完成)
1. 在learn目录下新建一个templates文件夹,里面新建一个home.html (1) 很简单的,就直接右键learn,新建文件夹,完成后,继续右键templates,创建文档,后缀名为ht ...
- Vue vs React:你需要知道的一切
Vue 和 React 是创建 JavaScript 网络应用程序最常用的两种工具.但我们该如何在两者之间做出选择呢?在本篇 Vue 与 React 的对比中,我们将尝试找出答案.我们将回顾每种工具的 ...
- KRPANO 最新官方文档中文版(持续更新)
KRPano最新官方文档中文版分享,后续持续更新: http://docs.krpano.tech/ 本博文发表于:http://www.krpano.tech/archives/849 发布者:屠龙 ...
- 领域驱动模型DDD(四)——Eventuate Tram Saga源码讲解
前言 虽然本人一直抱怨<微服务架构设计模式>中DDD模式下采用的Eventuate Tram Saga不算简单易用,但是为了更加深入了解原文作者的设计思路,还是花了点时间去阅读源码,并且为 ...
- Note -「Polynomial」
Part. 1 FFT Part. 1-1 Main 对于一个 \(n\) 次多项式 \(F(x)=\sum_{i=0}^{n}a_{i}x^{i}\),在平面直角坐标系中可以由 \(n+1\) 个点 ...
- mpi转以太网连接200plc通信不上实际问题和解决方法
西门子S7200plc通信不上实际问题和解决方法 现场通信的同学在现场调试的时候,现在特别是做项目改造的项目,西门子S7200plc通信面临淘汰,但是在改造的项目中还能经常看到他们的身影,下面我们就来 ...
- 用现代C++写一个python的简易型list
std::variant介绍:en.cppreference.com/w/cpp/utility/variant 通过泛型模板(仅提供了int, double, string三种类型的存储),实现了a ...
- 给网站添加xml地图索引写法和应用
使用php给网站添加xml地图索引写法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ...
- Redis系列之——Redis-Cluster
文章目录 一 Redis Cluser介绍背景 1.1问题 1.2 解决 二 数据分布(分布式数据库) 2.1 存在问题 2.2 分区方式 2.2.1 顺序分区 2.2.2 哈希分区 2.2.2 .1 ...