P5677
[GZOI2017]配对统计
这个真的蛮难想的。。。
本来想把不等式变形的。。。后来发现直接盯着不等式找性质就可以了。。。简单来说就是对于
然后排序检查相邻的两个数即可,可在
那么现在处理这个计数。
最基本的原理是:将询问按照
那么根据这个原理,我们设计了一个离线算法,因为这个
然后比较棘手的是
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<cmath>
#include<map>
#include<vector>
#define ll long long
using namespace std;
const ll N=3e5;
struct node{
ll v,id;
}a[N+5];
struct _node{
ll l,r;
}pr[N*2+5];
struct __node{
ll l,r,id;
}q[N+5];
ll n,m,tot,j,ans;
ll c[N+5];
void _add(ll x) {
for(;x<=n;x+=x&-x) c[x]++;
}
ll ask(ll x) {
ll res=0;
for(;x;x-=x&-x) res+=c[x];
return res;
}
void add(ll l,ll r) {
if(l>r) swap(l,r);
pr[++tot].l=l;pr[tot].r=r;
}
inline ll read() {
ll ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9') {if(ch=='-') f=-f;ch=getchar();}
while(ch>='0'&&ch<='9') {ret=(ret<<3)+(ret<<1)+ch-'0';ch=getchar();}
return ret*f;
}
void write(ll x) {
if(x<0) {x=-x;putchar('-');}
if(x>9) write(x/10);
putchar(x%10+48);
}
bool cmp(node x,node y) {
return x.v<y.v;
}
bool _cmp(_node x,_node y) {
return x.r<y.r;
}
bool __cmp(__node x,__node y) {
return x.r<y.r;
}
int main() {
n=read();m=read();
for(ll i=1;i<=n;i++) {
a[i].v=read();a[i].id=i;
}
sort(a+1,a+n+1,cmp);
add(a[1].id,a[2].id);
add(a[n-1].id,a[n].id);
for(ll i=2;i<=n-1;i++) {
if(a[i].v-a[i-1].v>=a[i+1].v-a[i].v) add(a[i].id,a[i+1].id);
if(a[i].v-a[i-1].v<=a[i+1].v-a[i].v) add(a[i-1].id,a[i].id);
}
sort(pr+1,pr+tot+1,_cmp);
for(ll i=1;i<=m;i++) {
q[i].l=read();q[i].r=read();q[i].id=i;
}
sort(q+1,q+m+1,__cmp);
j=1;
for(ll i=1;i<=m;i++) {
while(pr[j].r<=q[i].r&&j<=tot) {
_add(pr[j].l);
j++;
}
ans=ans+q[i].id*(j-1-ask(q[i].l-1));
}
write(ans);
return 0;
}