zoukankan      html  css  js  c++  java
  • #回滚莫队#AT1219 歴史の研究

    洛谷题目
    AT1219


    分析

    不满足区间减性质的运算,如最值,就不能用普通莫队求,
    考虑回滚莫队,它的核心思想就是若区间在块内直接暴力,
    否则将右端点从小到大排序,右端点按普通莫队求,那么左端点由于只在一个块内,
    所以询问完跳到块末,由于块的大小为根号,影响复杂度的实际上是右端点,
    然后每次处理完相同左端点块清除标记


    代码

    #include <cstdio>
    #include <cctype>
    #include <cmath>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=100011; typedef long long lll;
    struct rec{int l,r,rk;}q[N]; lll Ans[N];
    int a[N],b[N],pos[N],c[N],m,tot,bl,n,cnt[N],cnT[N];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(lll ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    bool cmp(rec x,rec y){return (pos[x.l]^pos[y.l])?(pos[x.l]<pos[y.l]):(x.r<y.r);}
    inline signed min(int a,int b){return a<b?a:b;}
    inline lll max(lll a,lll b){return a>b?a:b;}
    inline lll calc(int l,int r){
    	rr lll ans=0;
    	for (rr int i=l;i<=r;++i){
    		++cnT[a[i]];
    		ans=max(ans,1ll*cnT[a[i]]*b[a[i]]);
    	}
    	for (rr int i=l;i<=r;++i) --cnT[a[i]];
    	return ans;
    }
    signed main(){
    	n=iut(),m=iut(),bl=sqrt(n)+1;
    	for (rr int i=1;i<=n;++i) b[i]=a[i]=iut(),pos[i]=(i-1)/bl+1;
    	sort(b+1,b+1+n),tot=unique(b+1,b+1+n)-b-1;
    	for (rr int i=1;i<=n;++i) a[i]=lower_bound(b+1,b+1+tot,a[i])-b;
    	for (rr int i=1;i<=m;++i) q[i]=(rec){iut(),iut(),i};
    	sort(q+1,q+1+m,cmp);
    	for (rr int L=1,R;L<=m;L=R+1){
    		rr int now=pos[q[L].l],Tot=0; rr lll ans=0;
    		rr int Ed=min(now*bl,n),l=Ed+1,r=Ed;
    		for (R=L;pos[q[R].l]==now;++R); --R;
    		for (rr int i=L;i<=R;++i)
    		if (now==pos[q[i].r]) Ans[q[i].rk]=calc(q[i].l,q[i].r);
    		else{
    			while (r<q[i].r){
    				++cnt[a[++r]],c[++Tot]=a[r];
    				ans=max(ans,1ll*cnt[a[r]]*b[a[r]]);
    			}
    			rr lll tmp=ans;
    			while (l>q[i].l)
    				++cnt[a[--l]],ans=max(ans,1ll*cnt[a[l]]*b[a[l]]);
    			Ans[q[i].rk]=ans,ans=tmp;
    			while (l<=Ed) --cnt[a[l++]];
    		}
    		for (rr int i=1;i<=Tot;++i) --cnt[c[i]];
    	}
    	for (rr int i=1;i<=m;++i)
    	    print(Ans[i]),putchar(10);
    	return 0;
    }
    
  • 相关阅读:
    java操作练习
    java认知
    java了解
    抽象类及抽象类
    杨辉三角实例菱形实例
    案例分析之运行顺序
    Object类的方法,toString的重写.
    多态
    类的继承
    面对对象
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13945737.html
Copyright © 2011-2022 走看看