好吧今天又考试了,idy002之光不灭……考试时蜜汁样例数据坑死一片,idy估计是午觉没睡好出的题。
第一题,树状数组。
那么它的一个逆序对是一个二元组:< i; j > 满足i < j 且ai > aj,其中i; j 2 [1; n]。
我们称一个序列所包含的逆序对的个数为这个序列的逆序对数。
那么问题来了:
我给出一个长度为n 的序列,需要你计算:
a1, a2……an-1, an
a,a3 ……an, a1
a3, a4……a1, a2
……
an, a1…… an-2,an-1
这n 个序列的逆序对之和。
Input输入文件包含2 行:
第1 行1 个整数:n,表示给定序列的长度。
第2 行n 个整数:a1 a2 : : : an,表示初始序列。
Output
输出n 个序列的逆序对的和。
(样例有坑,input 3 2 2 3 output 3)
#include "cstdio"
#include "cstring"
#include "algorithm"
#define N 1000010
using namespace std;
int a[2 * N], bit[N * 24], n, m;
long long ans = 0, cur = 0;
int lowbit( int x ){
return x & ( -x );
}
/*void modify( int pos, int delta ){
for( int i = pos; i <= n; i += lowbit( i ) )
bit[i] += delta;
}
int query( int rg ){
int rt = 0;
for( int i = rg; i; i -= lowbit( i ) )
rt += bit[i];
return rt;
} *//两种树状数组
void modify(int pos,int delta){
int x=pos;
while(x<=n){
bit[x]+=delta;
x+=lowbit(x);
}
}
int query(int pos){
int x=pos,rt=0;
while(x){
rt+=bit[x];
x-=lowbit(x);
}
return rt;
}
int main(){
freopen("rotinv.in", "r", stdin);
freopen("rotinv.out", "w", stdout);
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
a[ n + i ] = a[i];
}
for(int i = 1; i <= n; i++){
cur += (i - 1) -query( a[i] );
modify( a[i], +1 );
}
for(int i = n + 1; i <= n + n; i++){
modify( a[i-n], -1);
cur += (n - 1) -query( a[i] );
cur -= query( a[i - n] - 1 );
modify( a[i], +1 );
ans += cur;
}
printf("%I64d", ans);
return 0;
}
第二题,不知道是什么听起来非常高端的数据结构。
你有一堆柱子,它们竖直地并排摆放在桌子上,它们的高度分别是:
h1,h2……hn-1,hn
你从前往后看,能够看见的柱子个数为这个柱子序列的“可见度”(能够看见柱子i 当且仅当hj < hi任意j < i)。
现在给你一个长度为n 的序列,还有m 个询问,每次询问某个区间[l, r] 的柱子单独拿出来后,其可见度是多大。
Input
第1 行2 个整数:n m,表示给出的柱子序列的长度和询问数。
第2 行n 个整数:a1,a2……an-1,an,表示每根柱子对应的高度。
接下来m 行,每行2 个整数:l r,表示对区间[l,r] 进行询问。
input
5 4
1 3 2 4 2
1 4
2 4
1 3
2 3
output3
2
2
1
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100010
using namespace std;
int n,m,tot=0;
int a[N],head[N],q[N],b[N];
struct node{
int pre,to;
}edge[N];
void adde(int from,int to){
tot++;
edge[tot].pre=head[from];
edge[tot].to=to;
head[from]=tot;
}
int dfs(int u,int r){
for(int i=head[u];i;i=edge[i].pre){
int v=edge[i].to;
if(v<=r){
dfs(v,r);
tot++;
}
}
return tot;
}
int main(){
freopen("rise.in","r",stdin);
freopen("rise.out","w",stdout);
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(register int i=1;i<=n;i++){
for(register int j=i+1;j<=n;j++){
if(a[j]>a[i]){
adde(i,j);
break;
}
}
}
while(m--){
int u,v;
tot=1;
scanf("%d%d",&u,&v);
printf("%d\n",dfs(u,v));
}
return 0;
}