题意:给定一个长度为 m 的序列,序列中的数都在 1~n 之间,现在令 pi(n) 表示序列 {i,1,2,..,i-1,i+1,..,n};现在对于p1(n)~pn(n) 计算出 ,pos(pi(n),3) 表示 3 在这个排列的下标是多少;
分析:差分一下就可以了;假设现在查询的两个元素是 l , r (l<r) 那么对于pi
①若 i<l || i>r ,则 pi 不受影响,即 pi 的 第 l 个元素与第 r 个元素的相对位置不受影响;
②若 l<i<r ,即 pi 的 第 l 个元素与第 r 个元素的相对位置减1,因为 序列pi 中第 i 个元素被调走去了第一位 ,l => l+1 , r => r;所以相对位置减 1;
③若 i==l ,即 pi 的 第 l 个元素与第 r 个元素的相对位置为 r-1,因为 序列 pi 中第 l 个元素被调走去了第一位,l =>1 , r=>r ,
则相对位置为 r-1;
④若 i==r ,即 pi 的 第 l 个元素与第 r 个元素的相对位置为 l,因为 序列 pi 中第 r 个元素被调走去了第一位,l => l+1 ,r =>1 ,则相对位置为 l;
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N = 2E5+10;
ll s[N],x[N];
void up(int l,int r,int w){
s[l]+=w,s[r+1]-=w;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) scanf("%d",&x[i]);
for(int i=2,l,r;i<=m;i++){
l=x[i-1],r=x[i];
if(l>r) swap(l,r);
if(l==r) continue;
up(1,l-1,r-l);
up(r+1,n,r-l);
up(l+1,r-1,r-l-1);
up(l,l,r-1);
up(r,r,l);
}
for(int i=1;i<=n;i++) printf("%lld ",s[i]+=s[i-1]);
}