zoukankan      html  css  js  c++  java
  • 【 Gym

    BUPT2017 wintertraining(15) #4B
    Gym - 101138D

    题意

    a数组大小为n。(1 ≤ n ≤ 50 000) (1 ≤ q ≤ 50 000)(1 ≤ ai ≤ n)
    q个查询,询问两个区间相同的数有多少对。

    题解

    [sl,sr]和[tl,tr]区间相同的数的对数可以用(f[sl,tr]-f[sl,tl]-f[sr,tr]+f[sr,tr])计算。(f[l,r])为区间[l,r]内相同的数的对数。
    对于每个询问,记录需要计算的f的区间,然后按l/sqrt(n)为第一关键字,r为第二关键字排序。
    如果计算完f[l,r],那么计算f[l1,r1]时,可以由[l,r]区间转移到[l1,r1]区间,相当于移动左右端点的指针。

    随便写写的时间复杂度分析(n为计算的区间个数):

    pos[i]记录区间i的第一关键字。
    相邻的两个计算区间(排序后),若pos相同,左指针移动最远(sqrt n)步,最坏情况就是n个区间都移动这么多步,总的最多(nsqrt n)步。
    若pos不同,总的最多是(n)步。
    pos相同的所有区间,右指针最多共移动n步(1到n),共(sqrt n)个pos值,总的最多移动(nsqrt n)步。
    pos不同时,右指针最多移动n步(n到1),共(sqrt n)个pos,总的最多移动(nsqrt n)步。
    因为计算所有区间的过程,左指针最多移动(nsqrt n)步,右指针最多移动了(nsqrt n)步。因此复杂度是(O(nsqrt n))

    代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cmath>
    #define N 50005
    #define ll long long
    using namespace std;
    int n,m,a[N],qs,pos[N];
    ll ans[N],s[N];
    struct node{int l,r,d;}p[N<<2];
    bool cmp(node a,node b){
    	return pos[a.l]<pos[b.l]||pos[a.l]==pos[b.l]&&a.r<b.r;
    }
    void add(int p,ll &f){
    	f+=s[a[p]]++;
    }
    void sub(int p,ll &f){
    	f-=--s[a[p]];
    }
    int main() {
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    	for(int i=1,j=1;i<=n;i++){
    		if(i%(int)sqrt(n)==0)j++;
    		pos[i]=j;
    	}
    	scanf("%d",&qs);
    	for(int i=1;i<=qs;i++){
    		int sl,sr,tl,tr;
    		scanf("%d%d%d%d",&sl,&sr,&tl,&tr);
    		sr++;tl--;
    		//[sl,tr]-[sl,tl-1]-[sr+1,tr]+[sr+1,tl-1]
    		p[m++]=(node){sl,tr,i};p[m++]=(node){sl,tl,-i};
    		p[m++]=(node){sr,tr,-i};p[m++]=(node){sr,tl,i};
    	}
    	sort(p,p+m,cmp);
    	int L=n+1,R=n;
    	ll num=0;
    	for(int i=0;i<m;i++){
    		while(L<p[i].l)
    			sub(L++,num);
    		while(L>p[i].l)
    			add(--L,num);
    		while(R>p[i].r)
    			sub(R--,num);
    		while(R<p[i].r)
    			add(++R,num);
    		if(p[i].d>0)ans[p[i].d]+=num;
    		else ans[-p[i].d]-=num;
    	}
    	for(int i=1;i<=qs;i++)printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    P1121 环状最大两段子段和
    无题
    cdoj 1485 柱爷搞子串 sam treap
    自然数幂和
    Gym 100341C AVL Trees NTT
    线性筛分解质因子
    codeforces 366 Ant Man dp
    UVALive 6914 Maze Mayhem 轮廓线dp
    hdu 5790 Prefix 字典树 主席树
    莫比乌斯反演个人小结
  • 原文地址:https://www.cnblogs.com/flipped/p/6408169.html
Copyright © 2011-2022 走看看