zoukankan      html  css  js  c++  java
  • 【JZOJ5428】【NOIP2017提高A组集训10.27】查询

    题目

    给出一个长度为n的序列a[]
    给出q组询问,每组询问形如(<x,y>),求a序列的所有区间中,数字x的出现次数与数字y的出现次数相同的区间有多少个。

    分析

    我们可以维护一个前缀和sum,遇到x时加1,遇到y减1。
    那么对于区间[l,r],如果sum[r]-sum[l-1]=0,则这个区间合法。
    我们可以用桶来求出(<x,y>)的合法区间个数。
    于是我们(O(N^3))预处理每一个(<x,y>)
    但是这显然会超时。
    因为只有有x和y时位置才是有用的,
    我们可以记录x和y所在的位置,这样就可以讲其中很多没用的位置压缩掉。
    这样就是(O(N^2))的时间复杂度

    #include <cmath>
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <map>
    const int maxlongint=2147483647;
    const int mo=1e9+7;
    const int N=8005;
    using namespace std;
    map <int,int> g;
    int tot,a[N],tub[N*2],n,m,d[N],ans[N][N],num,q[N][N/7],re[N];
    int prt[20];
    void read(int &n)
    {
        char ch=' ';int q=0,w=1;
        for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
        if(ch=='-')w=-1,ch=getchar();
        for(;ch>='0' && ch<='9';ch=getchar())q=(q<<1)+(q<<3)+ch-'0';n=q*w;
    }
    void write(int x)
    {
    	if(x<0) putchar('-'),x=-x;
    	for(;x;x/=10) prt[++prt[0]]=x%10;
    	if(!prt[0]) prt[++prt[0]]=0;
    	for (;prt[0];putchar('0'+prt[prt[0]--]));
    }
    void pre()
    {
    	ans[0][0]=n*(n+1)/2;
    	for(int i=1;i<=tot;i++)
    	{
    		int num=0;
    		for(int j=1;j<=n;j++)
    			if(a[j]==i) d[++num]=j;
    		d[num+1]=n+1;
    		for(int j=0,dt;j<=num;j++) dt=d[j+1]-d[j]-1,ans[i][0]+=dt*(dt+1)/2;
    		ans[0][i]=ans[i][0];
    	}
    	for(int i=1;i<=tot;i++)
    	{
    		ans[i][i]=n*(n+1)/2;
    		for(int j=i+1,sum;j<=tot;j++)
    		{
    			if(i==1 && j==19)
    			{
    				printf("");
    			}
    			sum=0;
    			int p=0,p1=0,mx;
    			if(q[i][p+1]>q[j][p1+1]) mx=q[j][++p1],sum--;
    			else mx=q[i][++p],sum++;
    			tub[n]=mx,ans[i][j]+=mx*(mx-1)/2;
    			while(p<q[i][0] || p1<q[j][0])
    			{
    				if(q[i][p+1]>q[j][p1+1])
    				{
    					p1++;
    					ans[i][j]+=(q[j][p1]-mx-1)*(q[j][p1]-mx)/2+(q[j][p1]-mx)*tub[n+sum];
    					tub[n+sum]+=q[j][p1]-mx;
    					sum--;
    					mx=q[j][p1];
    				}
    				else
    				{
    					p++;
    					ans[i][j]+=(q[i][p]-mx-1)*(q[i][p]-mx)/2+(q[i][p]-mx)*tub[n+sum];
    					tub[n+sum]+=q[i][p]-mx;
    					sum++;
    					mx=q[i][p];
    				}
    			}
    			ans[i][j]+=(n-mx+1)*tub[sum+n]+(n-mx+1)*(n-mx)/2;
    			ans[j][i]=ans[i][j];
    			p=0,p1=0,mx=0;
    			for(int k=-q[j][0];k<=q[i][0];k++) tub[k+n]=0;
    		}
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		if(!g[a[i]]) g[a[i]]=++tot;
    		re[g[a[i]]]=a[i];
    		a[i]=g[a[i]];
    		q[a[i]][++q[a[i]][0]]=i;
    	}
    	for(int i=1;i<=tot;i++) q[i][q[i][0]+1]=n+1;
    	pre();
    	for(int x,y;m--;)
    	{
    		read(x),read(y);
    		x=g[x],y=g[y];
    		if(ans[x][y]==14576)
    		{
    			printf("");
    		}
    		printf("%d
    ",ans[x][y]);
    	}
    }
    
  • 相关阅读:
    jQuery的deferred对象详解 jquery回调函数
    Table does not have the identity property. Cannot perform SET operation.
    SQLServer中merge函数用法详解
    jQuery事件命名空间多事件绑定自定义事件js 命名空间 javascript命名空间
    you have mixed tabs and spaces fix this
    java.lang.NoClassDefFoundError: javax/servlet/http/HttpServletRequest
    SQLServer 窗口函数
    TFS中查看我的所有签入迁出记录 TFS 怎么查看所有的修改
    日历控件My97DatePicker WdatePicker屏蔽 onchange的解决方法
    【Python】生成词云
  • 原文地址:https://www.cnblogs.com/chen1352/p/9079682.html
Copyright © 2011-2022 走看看