题目背景
最近,小 Z 对冒泡排序产生了浓厚的兴趣。
下面是冒泡排序的伪代码:
输入: 一个长度为 n 的序列 a[1...n]
输出: a 从小到大排序后的结果
for i = 1 to n do:
for j = 1 to n - 1 do
if (a[j] > a[j + 1])
交换 a[j] 与 a[j + 1] 的值
冒泡排序的交换次数被定义为在排序时进行交换的次数,也就是上面冒泡排序伪代码第六行的执行次数。他希望找到一个交换次数尽量少的序列。
题目描述
小 Z 所研究的序列均由非负整数构成。它的长度为 nn,且必须满足 mm 个附加条件。其中第 ii 个条件为:下标在 [L_i, R_i][Li,Ri] 中的数,即 a_{L_i}, a_{L_{i+1}},\dots,a_{R_i}aLi,aLi+1,…,aRi 这些数,其最小值恰好为 \boldsymbol{V_i}Vi。
他知道冒泡排序时常会超时。所以,他想要知道,在所有满足附加条件的序列中,进行冒泡排序的交换次数的最少值是多少。
输入格式
本题有多组数据。
输入的第一行包含一个正整数 TT。
对于每组数据,第一行包含两个正整数 n,mn,m。数据保证 1 \leq n,m \leq 10^61≤n,m≤106。
接下来 mm 行,每行三个非负整数 L_i, R_i, V_iLi,Ri,Vi,表示一组附加条件。数据保证 1 \leq L_i \leq R_i \leq n1≤Li≤Ri≤n、0 \leq V_i \leq 10^90≤Vi≤109。
输出格式
输出共 TT 行,每行一个整数。
对于每组数据,如果存在满足这 mm 个附加条件的序列,则输出在所有满足附加条件的序列中,冒泡排序交换次数的最小值。如果不存在满足所有条件的序列,则输出 -1−1。
输入输出样例
输入 #1复制
1 3 2 1 1 2022 2 3 39
输出 #1复制
1
说明/提示
【样例解释 #1】
这组数据的约束条件为 a_1 = 2022, \min\{a_2, a_3\} = 39a1=2022,min{a2,a3}=39。
若 a_2 = 39a2=39,且 39 \leq a_3 < 202239≤a3<2022,则冒泡排序只有第一轮有交换操作,这一轮交换了 a_1, a_2a1,a2 和 a_2, a_3a2,a3,总交换次数为 22。
若 a_2 = 39a2=39,且 a_3 \geq 2022a3≥2022,则冒泡排序只有第一轮有交换操作,这一轮仅仅交换 a_1, a_2a1,a2,总交换次数为 11。
若 a_3 = 39a3=39,且 39 < a_2 < 202239<a2<2022,则冒泡排序算法第一轮交换 a_1, a_2a1,a2 和 a_2, a_3a2,a3,第二轮交换 a_1, a_2a1,a2。总交换次数为 33。
若 a_3 = 39a3=39,且 a_2 \geq 2022a2≥2022,则冒泡排序算法第一轮交换 a_2, a_3a2,a3,第二轮交换 a_1, a_2a1,a2。总交换次数为 22。
因此,交换次数的最小值为 11。
【样例 #2】
见附件中的 bubble/bubble2.in
与 bubble/bubble2.ans
。
【样例 #3】
见附件中的 bubble/bubble3.in
与 bubble/bubble3.ans
。
这个样例满足测试点 8 \sim 108∼10 的条件。
【样例 #4】
见附件中的 bubble/bubble4.in
与 bubble/bubble4.ans
。
这个样例满足测试点 13 \sim 1413∼14 的条件。
【样例 #5】
见附件中的 bubble/bubble5.in
与 bubble/bubble5.ans
。
这个样例满足测试点 15 \sim 1615∼16 的条件。
【样例 #6】
见附件中的 bubble/bubble6.in
与 bubble/bubble6.ans
。
这个样例满足测试点 23 \sim 2523∼25 的条件。
【数据范围】
本题共 2525 个测试点。全部测试点满足:1 \leq T \leq 10001≤T≤1000,1 \leq \sum n, \sum m \leq 10^61≤∑n,∑m≤106,1 \leq L_i \leq R_i \leq n1≤Li≤Ri≤n,0 \leq V_i \leq 10^90≤Vi≤109。
其中 \sum n, \sum m∑n,∑m 分别表示所有测试点的 nn 的总和和 mm 的总和。\sum n^2, \sum m^2, \sum n^3, \sum m^3∑n2,∑m2,∑n3,∑m3 的含义类似。
测试点 | 数据范围 | 特殊性质 |
---|---|---|
1 \sim 41∼4 | n,m \leq 7n,m≤7,且最多 22 组数据不满足 n, m \leq 5n,m≤5 | |
5 \sim 75∼7 | n,m \leq 17n,m≤17,且最多 33 组数据不满足 n, m \leq 9n,m≤9 | A |
8 \sim 108∼10 | n,m \leq 100n,m≤100,\sum n^3,\sum m^3 \leq 4 \times 10^7∑n3,∑m3≤4×107 | A |
11 \sim 1211∼12 | n,m \leq 2000n,m≤2000,\sum n^2,\sum m^2 \leq 4 \times 10^7∑n2,∑m2≤4×107 | A |
13 \sim 1413∼14 | n,m \leq 2000n,m≤2000,\sum n^2,\sum m^2 \leq 4 \times 10^7∑n2,∑m2≤4×107 | B |
15 \sim 1615∼16 | n,m \leq 2000n,m≤2000,\sum n^2,\sum m^2 \leq 4 \times 10^7∑n2,∑m2≤4×107 | C |
17 \sim 1817∼18 | n,m \leq 2000n,m≤2000,\sum n^2,\sum m^2 \leq 4 \times 10^7∑n2,∑m2≤4×107 | |
1919 | \sum n,\sum m \leq 10^6∑n,∑m≤106 | A |
2020 | \sum n,\sum m \leq 10^6∑n,∑m≤106 | B |
21 \sim 2221∼22 | \sum n,\sum m \leq 10^6∑n,∑m≤106 | C |
23 \sim 2523∼25 | \sum n,\sum m \leq 10^6∑n,∑m≤106 |
特殊性质 A:对于 1 \leq i \leq m1≤i≤m,0 \leq V_i \leq 10≤Vi≤1。
特殊性质 B:对于 1 \leq i \leq m1≤i≤m,L_i = R_iLi=Ri。
特殊性质 C:输入给出的 mm 个区间 [L_i, R_i][Li,Ri] 两两不相交。
【提示】
本题的部分测试点输入量较大。我们建议你使用较为快速的读入方式。
附件下载
bubble.zip6.95MB
看之前先看提示:本题难度为NOI/NOI+/CTSC,先了解思路再来
AC代码:
#include<bits/stdc++.h>
#define re register
using namespace std;
inline int read(){
re int t=0;re char v=getchar();
while(v<'0')v=getchar();
while(v>='0')t=(t<<3)+(t<<1)+v-48,v=getchar();
return t;
}
int t,n,m,a[1000002],A,B,L[1000002],R[1000002],V[1000002],W[1000002],mn[4000002],mnp[4000002],tg[4000002],fa[1000002],V1[1000002],V2[1000002],c[1000002],ans1,ans2;
char s[1000002];
inline void add(re int x){for(;x;x^=x&(-x))++c[x];}
inline int ask(re int x,re int s=0){for(;x<=m;x+=x&(-x))s+=c[x];return s;}
inline void build(re int p,re int l,re int r){
tg[p]=mn[p]=0,mnp[p]=l;
if(l==r)return;
re int mid=l+r>>1;
build(p<<1,l,mid),build(p<<1|1,mid+1,r);
}
inline void pu(re int p){
mn[p]=min(mn[p<<1],mn[p<<1|1]);
if(mn[p]==mn[p<<1])mnp[p]=mnp[p<<1];
else mnp[p]=mnp[p<<1|1];
}
inline void Add(re int x,re int y){mn[x]+=y,tg[x]+=y;}
inline void pd(re int p){
if(tg[p])Add(p<<1,tg[p]),Add(p<<1|1,tg[p]),tg[p]=0;
}
inline void add(re int p,re int l,re int r,re int x,re int y,re int z){
if(l>=x&&r<=y)return Add(p,z);
pd(p);
re int mid=l+r>>1;
if(x<=mid)add(p<<1,l,mid,x,y,z);
if(y>mid)add(p<<1|1,mid+1,r,x,y,z);
pu(p);
}
inline void ask(re int p,re int l,re int r,re int x,re int y){
if(l>=x&&r<=y){
if(mn[p]<ans2)ans2=mn[p],ans1=mnp[p];
return;
}pd(p);
re int mid=l+r>>1;
if(x<=mid)ask(p<<1,l,mid,x,y);
if(y>mid)ask(p<<1|1,mid+1,r,x,y);
}
struct node{int x,y;bool operator <(const node A)const{return x<A.x;};};
inline int root(re int x){return x==fa[x]?x:fa[x]=root(fa[x]);}
vector<node>G[1000002];
int main(){
t=read();
while(t--){
n=read(),m=read();
for(re int i=1;i<=m;++i)L[i]=read(),R[i]=read(),V[i]=W[i]=read(),G[i].clear();
for(re int i=1;i<=n;++i)V1[i]=V2[i]=0;
sort(W+1,W+m+1);
for(re int i=1;i<=m;++i)V[i]=lower_bound(W+1,W+m+1,V[i])-W,G[V[i]].push_back((node){L[i],R[i]});
for(re int i=1;i<=n+1;++i)fa[i]=i;re bool ia=1;
for(re int i=m;i&&ia;--i)if(G[i].size()){
sort(G[i].begin(),G[i].end());
re int lst=n+1;
for(re int j=G[i].size()-1;~j&&ia;--j)
if(G[i][j].y<lst){
re int pos=root(G[i][j].x);
V1[pos]=i,ia&=pos<=G[i][j].y,lst=pos;
}
for(auto z:G[i])
for(re int j=root(z.x);j<=z.y;j=root(j))V2[j]=i,fa[j]=j+1;
}if(!ia){puts("-1");continue;}build(1,0,m+1);long long ans=0;
for(re int i=1;i<=m;++i)c[i]=0;
for(re int i=1;i<=n;++i)if(V1[i])ans+=ask(V1[i]+1),add(V1[i]),add(1,0,m+1,V1[i]+1,m+1,1);
for(re int i=1;i<=n;++i)
if(V1[i])add(1,0,m+1,V1[i]+1,m+1,-1),add(1,0,m+1,0,V1[i]-1,1);
else{
ans2=1e9,ask(1,0,m+1,V2[i],m+1);
ans+=ans2;
if(ans1)add(1,0,m+1,0,ans1-1,1);
}
printf("%lld\n",ans);
}
}
给个关注吧~~~