P4396

第一问是求 \(\sum\limits_{i=l}^r [x\le a_i \le y]\)

我们发现这个东西直接莫队是四个关键字,于是我们考虑这玩意的性质。

发现这个区间可以差分。

于是把一个询问拆成两个:\(\sum\limits_{i=l}^r [1\le a_i \le y]-\sum\limits_{i=l}^r [1\le a_i \le x-1]\)

这样就可以做了。

同样第二问也一样差分。

#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
struct node{
     int l,r,k,i;
}q[N];
ll a[N];
int pos[N];
int t[N];
inline int read()
{
	int num=0,f=1;char c=getchar();
	while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
	while(c>47&&c<58)num=num*10+(c^48),c=getchar();
	return num*f;
}
#define num now
int cnt,now,qwq;
void add(int x){
        qwq+=((!t[a[x]]++)&&a[x]<=num);
        cnt+=a[x]<=num;
}
void del(int x){
        qwq-=((!--t[a[x]])&&a[x]<=num);
        cnt-=a[x]<=num;
}
int ans[N],qaq[N];
int main()
{
    int n=read(),m=read();
    int siz=pow(n,0.66666666);
    for(int i=1;i<=n;i++){
        a[i]=read();
        pos[i]=i/siz;
    }
    for(int i=1;i<=m;i++){
       q[i].l=read(),q[i].r=read(),q[i].k=read()-1;
       q[i+m].l=q[i].l,q[i+m].r=q[i].r,q[i+m].k=read();
        q[i].i=i;q[i+m].i=i+m;
    }
    sort(q+1,q+1+m+m,[](node x,node y){
         if(pos[x.l]!=pos[y.l])return pos[x.l]<pos[y.l];
         else if(pos[x.r]!=pos[y.r])return pos[x.r]<pos[y.r];
         else return x.k<y.k;
         });
    int l=1,r=0;
    cnt=0,now=q[1].k;
    for(int i=1;i<=m+m;i++){
        while(r<q[i].r)add(++r);
 //       cout<<cnt<<' '<<q[i].k<<endl;
        while(l>q[i].l)add(--l);
        while(r>q[i].r)del(r--);
        while(l<q[i].l)del(l++);
        while(now<q[i].k)cnt+=t[++now],qwq+=!!t[now];
        while(now>q[i].k)qwq-=!!t[now],cnt-=t[now--];
        ans[q[i].i]=cnt;
        qaq[q[i].i]=qwq;
    }
//    for(int i=1;i<=m+m;i++)printf("%d ",ans[i]);puts("");
    for(int i=1;i<=m;i++)printf("%d %d\n",ans[i+m]-ans[i],qaq[i+m]-qaq[i]);
    return 0;
}
posted @ 2021-06-16 20:55  cmll02  阅读(57)  评论(0)    收藏  举报