码迷,mamicode.com
首页 > 其他好文 > 详细

【LOJ2254】SNOI2017一个简单的询问

时间:2017-07-07 21:34:02      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:opera   bool   color   blog   swa   code   names   一个   for   

莫队,每次询问的是两个区间,就把区间拆开,分开来算就好了。

借鉴了rank1大佬的玄学排询问的姿势。

#include<bits/stdc++.h>
#define N 50010
typedef long long ll;
using namespace std;
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch==-)f=-1;}while(ch<0||ch>9);
    do{x=x*10+ch-0;ch=getchar();}while(ch>=0&&ch<=9);
    return f*x;
}
int c1[N],c2[N],a[N],n,m,cnt;
struct Query{
    int l,r,id;
    bool operator < (const Query &ths) const {
        if(l/233!=ths.l/233) return l<ths.l;
        if(l/233&1) return r>ths.r;
        else return r<ths.r;
    }
}q[N<<2];
ll ans[N],tot=0,Ans=0;
int main(){
    n=read();for(int i=1;i<=n;i++)a[i]=read();
    m=read();
    for(int i=1;i<=m;i++){
        int l1=read(),r1=read(),l2=read(),r2=read();
        q[++cnt]=(Query){r1,r2,i};
        if(l1>1)q[++cnt]=(Query){l1-1,r2,-i};
        if(l2>1)q[++cnt]=(Query){l2-1,r1,-i};
        if(l1>1&&l2>1)q[++cnt]=(Query){l1-1,l2-1,i};
    }
    for(int i=1;i<=cnt;i++)if(q[i].l>q[i].r)swap(q[i].l,q[i].r);
    sort(q+1,q+cnt+1);
    int l=1,r=0;c1[a[1]]++;
    for(int i=1;i<=cnt;i++){
        while(r<q[i].r)r++,Ans+=c1[a[r]],c2[a[r]]++;
        while(l<q[i].l)l++,Ans+=c2[a[l]],c1[a[l]]++;
        while(r>q[i].r)Ans-=c1[a[r]],c2[a[r]]--,r--;
        while(l>q[i].l)Ans-=c2[a[l]],c1[a[l]]--,l--;
        if(q[i].id<0) ans[-q[i].id]-=Ans;
        else ans[q[i].id]+=Ans;
    }
    for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
}

 

【LOJ2254】SNOI2017一个简单的询问

标签:opera   bool   color   blog   swa   code   names   一个   for   

原文地址:http://www.cnblogs.com/zcysky/p/7133909.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!