JZOJ 5428. 【NOIP2017提高A组集训10.27】查询

来源:互联网 发布:中世纪2优化9丹麦 编辑:程序博客网 时间:2024/05/14 21:12

题目

给出一个长度为n的序列a[]
给出q组询问,每组询问形如<x,y>,求a序列的所有区间中,数字x的出现次数与数字y的出现次数相同的区间有多少个。
数据范围
1<=n<=8000,1<=q<=500000,1<=x,y,a[i]<=109

题解

很容易想到,每次询问的时候, O(n)扫一遍,有一临时变量t,碰到x,t加一,碰到y,t减一,看前面有多少个t等于现在的t,按照这个计算答案。
然而这样做有个缺点:每一次都要O(n)扫一遍,其中有很多段t一样的,其实可以不用跑这些没有用的位置。
将x和y出现的位置找出来,排个序,然后做一遍。
总时间复杂度O(n2)
蒟蒻有个问题,怎么计算答案。
我们知道相邻两个位置之间的t是一样的,所以只要计算t=w(w为一个数)时的t的个数,即可得到答案。

代码

#include<iostream>#include<cstring>#include<cstdio>#include<cmath>#include<algorithm>#define N 8010#define P(a) putchar(a)#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;struct note{    int to,next;};note edge[N*10];struct note1{    int d,w;};note1 qu[N*2];int a[N],a1[N],b[N];int o[N],head[N],q1[N],q2[N];int ans[N][N];int i,j,k,l,r,l1,r1,n,q,sum,wz,last;int cnt[N*2],bz[N*2],cn,CNT,c1,c2,tot;int read(){    int res=0,fh=1;char ch;    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();    if(ch=='-')fh=-1,ch=getchar();    while(ch>='0'&&ch<='9')res=res*10+ch-'0',ch=getchar();    return res*fh;}void write(int x){    if(x>9)write(x/10);    P(x%10+'0');}int calc(int n){return n*(n+1)/2;}int calc1(int n){return n*(n-1)/2;}void lb(int x,int y){edge[++tot].to=y;edge[tot].next=head[x];head[x]=tot;}bool cmp(note1 x,note1 y){return x.d<y.d;}int main(){    freopen("query.in","r",stdin);    freopen("query.out","w",stdout);    n=read(),q=read();    fo(i,1,n)a[i]=read(),b[i]=a[i];    memcpy(a1,a,sizeof(a1));sort(b+1,b+n+1);cn=unique(b+1,b+n+1)-b-1;    fo(i,1,n){        a1[i]=lower_bound(b+1,b+cn+1,a1[i])-b;        o[a1[i]]=a[i];    }    fd(i,n,1)lb(a1[i],i);    fo(i,1,cn-1)        fo(j,i+1,cn){            c1=0;            for(k=head[i];k;k=edge[k].next)                qu[++c1].d=edge[k].to,qu[c1].w=1;            for(k=head[j];k;k=edge[k].next)                qu[++c1].d=edge[k].to,qu[c1].w=2;            sort(qu+1,qu+c1+1,cmp);            CNT++;            bz[8000]=CNT;cnt[8000]=qu[1].d;            qu[c1+1].d=n+1;            wz=8000;            ans[i][j]=calc1(qu[1].d);            fo(k,1,c1){                if(qu[k].w==1)wz++;else wz--;                if(CNT!=bz[wz]){                    bz[wz]=CNT;                    cnt[wz]=0;                }                ans[i][j]+=calc1(qu[k+1].d-qu[k].d)+cnt[wz]*(qu[k+1].d-qu[k].d);                cnt[wz]+=qu[k+1].d-qu[k].d;            }            ans[j][i]=ans[i][j];        }    fo(i,1,q){        l=read(),r=read();         l1=lower_bound(b+1,b+cn+1,l)-b;        r1=lower_bound(b+1,b+cn+1,r)-b;        if(o[l1]!=l)l=l1=0;if(o[r1]!=r)r=r1=0;        if((!l&&!r) ||(l1==r1)){            write(calc(n));P('\n');            continue;        }        if((!l&&r) || (!r&&l)){            sum=last=0;            if(r)l1=r1;            for(k=head[l1];k;k=edge[k].next){                sum+=calc(edge[k].to-1-last);                last=edge[k].to;            }            sum+=calc(n-last);            write(sum);P('\n');            continue;        }        write(ans[l1][r1]);        P('\n');    }    return 0;}
阅读全文
2 0
原创粉丝点击