这道题和树状数组求逆序数体很像,但是比赛的时候就是建立不好解题模型,比赛时好多人说需要离散化,看完别人的解题报告后才发现此题处理的便不是以前处理的值,这一题处理的是下标,用的是树状数组的离线算法,这题给我的感觉就是 自己的数状数组跟没学一个样,今后需要多多努力。
思路:分别对原始数组和要处理的值按从小到大排序,然后定义两个指针扫描排过序的数组,写两个条件判断,什么时候向树状数组插入,什么时候查询,
#include<iostream>
#include<stack>
#include<string.h>
#include<string>
#include<map>
#include<set>
#include<sstream>
#include<fstream>
#include<iterator>
#include<vector>
#include<algorithm>
#include<numeric>
#include<list>
#define N 100010
#define lowbit(x) (x&(-x))
#define CLR(arr,val) memset(arr,val,sizeof(arr))
using namespace std;
int s[N];
typedef struct node
{
int val;
int index;
}Node;
typedef struct snode
{
int L;
int R;
int val;
int index;
}Snode;
Node s1[N];
Snode s2[N];
int answer[N];
int n,m;
void add(int x)
{
while(x<=n)
{
s[x]++;
x+=lowbit(x);
}
}
int sum(int x)
{
int ans=0;
while(x>0)
{
ans+=s[x];
x-=lowbit(x);
}
return ans;
}
bool cmp(const Node& x,const Node& y)
{return x.val<y.val;}
bool cmp1(const Snode& x,const Snode& y)
{return x.val<y.val;}
void input(int& a)
{
char ch;
while((ch=getchar())>'9'||ch<'0') ;
for(a=0;ch>='0'&&ch<='9';ch=getchar()) a=a*10+ch-'0';
}
int main()
{
int T;
input(T);
for(int k=1;k<=T;++k)
{
input(n),input(m);
for(int i=1;i<=n;++i) input(s1[i].val),s1[i].index=i;
for(int i=0;i<m;++i) input(s2[i].L),input(s2[i].R),input(s2[i].val),s2[i].L++,s2[i].R++,s2[i].index=i;
sort(s1+1,s1+1+n,cmp);
sort(s2,s2+m,cmp1);
CLR(s,0);
CLR(answer,0);
int i=1,j=0;
while(j<m)
{
while(i<=n)
{
if(s1[i].val>s2[j].val) break;
add(s1[i].index);
i++;
}
while(j<m)
{
if(i<=n&&s1[i].val<=s2[j].val) break;
answer[s2[j].index]=sum(s2[j].R)-sum(s2[j].L-1);
j++;
}
}
printf("Case %d:\n",k);
for(int i=0;i<m;++i) printf("%d\n",answer[i]);
}return 0;
}

本文介绍了一种使用树状数组求解特定逆序数问题的方法,通过离散化处理下标而非值,实现对区间内逆序数的有效查询。文章提供了完整的代码示例,并解释了关键步骤。
2638

被折叠的 条评论
为什么被折叠?



