zoukankan      html  css  js  c++  java
  • [AHOI2013]作业

    传送门

    Description

    给定了一个长度为(n)的数列和若干个询问,每个询问是关于数列的区间表示数列的第(l)个数到第(r)个数),首先你要统计该区间内大于等于(a),小于等于(b)的数的个数,其次是所有大于等于(a),小于等于(b)的,且在该区间中出现过的数值的个数。

    (n,m leq 10^5)

    Solution

    非常简单的莫队题目

    追求更优的复杂度,可以采用(cdq)分治:

    我们发现其实原题可以简化成一个三维数点

    • (L leq ileq R)
    • (Aleq a[i] leq B)
    • (pre[i]leq L-1)

    于是把值离散一下,直接上(cdq)就行了


    Code 

    #include<bits/stdc++.h>
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)>(b)?(b):(a))
    #define reg register
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int MN=1e5+5;
    struct Node
    {
    	int x,y,z,sign,id;
    	bool operator < (const Node&_)const
    	{
    		if(z^_.z) return z<_.z;
    		return id<_.id;
    	}
    }a[MN*5],b[MN*5];
    int ans1[MN],ans2[MN],tot;
    int t[MN];
    void C(int x,int val){for(;x<=MN;x+=(x&-x))t[x]+=val;}
    int G(int x){int r=0;for(;x;x-=(x&-x))r+=t[x];return r;}
    void cdq(int l,int r)
    {
    	if(l==r) return;
    	reg int i,j,p=l,mid=(l+r)>>1;
    	cdq(l,mid);cdq(mid+1,r);
    	for(i=l,j=mid+1;i<=mid||j<=r;)
    		if(j>r||(i<=mid&&(a[i].y<a[j].y||(a[i].y==a[j].y&&a[i].id<a[j].id))))
    		{
    			if(!a[i].id) C(a[i].x,1);b[p++]=a[i++];
    		}
    		else
    		{
    			if(a[j].id)	ans2[a[j].id]+=a[j].sign*G(a[j].x);
    			b[p++]=a[j++];
    		}
    	for(i=l;i<=mid;++i) if(!a[i].id) C(a[i].x,-1);
    	for(i=l;i<=r;++i) a[i]=b[i];
    }
    int main()
    {
    	reg int i,j,N,M,num[MN],tt[MN],pre[MN],TT,_a,_b,_l,_r;
    	N=read();M=read();
    	for(i=1;i<=N;++i) num[i]=tt[i]=read();
    	std::sort(tt+1,tt+N+1);TT=std::unique(tt+1,tt+N+1)-tt-1;
    	memset(pre,0,sizeof pre);
    	for(i=1;i<=N;++i)
    		a[++tot]=(Node){i,j=std::lower_bound(tt+1,tt+TT+1,num[i])-tt,pre[j],0,0},pre[j]=i;
    	for(i=1;i<=M;++i)
    		_l=read(),_r=read(),
    		_a=std::lower_bound(tt+1,tt+TT+1,read())-tt,
    		_b=std::upper_bound(tt+1,tt+TT+1,read())-tt-1,
    		a[++tot]=(Node){_r,_b,_l-1,1,i},
    		a[++tot]=(Node){_r,_a-1,_l-1,-1,i},
    		a[++tot]=(Node){_l-1,_b,_l-1,-1,i},
    		a[++tot]=(Node){_l-1,_a-1,_l-1,1,i};
    	std::sort(a+1,a+tot+1);cdq(1,tot);
    	for(i=1;i<=tot;++i)
    		if(a[i].id) ans1[a[i].id]+=a[i].sign*G(a[i].x);
    		else C(a[i].x,1);
    	for(i=1;i<=M;++i) printf("%d %d
    ",ans1[i],ans2[i]);
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    windows下的定时任务设置详解
    php实现 字符串分割
    js进阶 11-7 jquery如何获取和改变元素的位置
    js进阶 11-6 jquery如何获取和设置元素的宽高(jquery多方法)
    详解PHP设置定时任务的实现方法
    详解PHP实现定时任务的五种方法
    百度echarts可以做什么
    前端开发框架对比(工具可以从框架中找)(好的框架,事半功倍)
    poj 3080 Blue Jeans
    ZOJ 3822 可能性DP
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/10658672.html
Copyright © 2011-2022 走看看