zoukankan      html  css  js  c++  java
  • bzoj3809: Gty的二逼妹子序列

    传送门:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3809

    思路:第一反应是莫队+树状数组,复杂度O(n^1.5*logn)

    TLE。。。

    于是就有了一个想法,分块维护美丽度,再套一个莫队。

    这样莫队移动端点就是O(1)的,每次询问就是O(n^0.5)

    然后就卡过了。。。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=100010,maxm=1000010;
    using namespace std;char ch,str[20];
    void read(int &x){
    	for (ch=getchar();!isdigit(ch);ch=getchar());
    	for (x=0;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
    }
    void print(int x){
    	if (!x) putchar('0');
    	int len;for (len=0;x;x/=10) str[++len]=x%10+'0';
    	for (int i=len;i;i--) putchar(str[i]);
    }
    
    struct que{
    	int l,r,a,b,id;
    	void scan(int x){read(l),read(r),read(a),read(b),id=x;}
    }q[maxm];
    int n,m,a[maxn],sz,s[maxn],bel[maxn],l[maxn],r[maxn],res,bloans[maxn],ans[maxm];
    bool cmp(que a,que b){return bel[a.l]==bel[b.l]?a.r<b.r:bel[a.l]<bel[b.l];}
    
    int query(int x,int y){
    	int tmp=0;
    	if (bel[x]==bel[y]) for (int i=x;i<=y;i++) tmp+=s[i]>0;
    	else{
    		for (int i=x;i<=r[bel[x]];i++) tmp+=s[i]>0;
    		for (int i=l[bel[y]];i<=y;i++) tmp+=s[i]>0;
    	}
    	for (int i=bel[x]+1;i<bel[y];i++) tmp+=bloans[i];
    	return tmp;
    }
    
    void add(int x){if (++s[x]==1) bloans[bel[x]]++;}
    void del(int x){if (--s[x]==0) bloans[bel[x]]--;}
    
    void work(){
    	for (int i=1,l=1,r=0;i<=m;i++){
    		for (;r<q[i].r;r++) add(a[r+1]);
    		for (;r>q[i].r;r--) del(a[r]);
    		for (;l<q[i].l;l++) del(a[l]);
    		for (;l>q[i].l;l--) add(a[l-1]);
    		ans[q[i].id]=query(q[i].a,q[i].b);
    	}
    	for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
    
    int main(){
    	//freopen("aa.in","r",stdin),freopen("aa.out","w",stdout);
    	scanf("%d%d",&n,&m);sz=sqrt(n);
    	for (int i=1;i<=n;i++) bel[i]=(i-1)/sz+1;
    	for (int i=1;i<=n;i++){
    		r[bel[i]]=i;
    		if (!l[bel[i]]) l[bel[i]]=i;
    	}
    	for (int i=1;i<=n;i++) read(a[i]);
    	for (int i=1;i<=m;i++) q[i].scan(i);
    	sort(q+1,q+1+m,cmp),work();
    	return 0;
    }


  • 相关阅读:
    Linux 中如何用源代码安装软件,以及如何卸载它
    Linux 中的 Install命令
    PHP 常用header头定义
    如何防止重复提交表单?
    如何从二维数组中的多个key中获取指定key的值?
    jquery的ajax全局事件详解
    PHP+MySQL分页显示示例分析
    javascript中的事件类型
    事件委托/事件代理,
    彻底弄懂JS的事件冒泡和事件捕获
  • 原文地址:https://www.cnblogs.com/thythy/p/5493540.html
Copyright © 2011-2022 走看看