zoukankan      html  css  js  c++  java
  • AT1219 歴史の研究

    附带权值的类区间众数问题?不是很好策啊

    发现题目没有强制在线,而且也只有询问操作,那么可以考虑莫队

    但是这里的莫队有一个很显著的特征,插入的时候很好维护答案,但是删除的时候不好回退

    那么有没有什么办法可以让莫队避免删除呢,当然是有的,而且这可以解决一大类类似问题

    考虑类似于一般莫队的分块操作,我们再排序时以左端点所在块为第一关键字,右端点为第二关键字

    那么我们可以根据左端点所在块分别处理这些询问

    首先如果左右端点在同一块内,那么很简单,直接暴力统计完了直接删光光就好了,这是(O(sqrt n))

    如果不是呢?由于此时的右端点是递增的,我们维护一个指针不停地往右边插入数即可,对于每一块的复杂度不会超过(O(n)),由于一共只有(sqrt n)块,所以总体还是(O(nsqrt n))

    可是这个时候左端点只是在同一块里并不是不变的。但是这部分的长度最多也是(sqrt n)啊,再不济和暴力一样做了在删了就好了吗,一共(n)个询问所以最多也是(O(nsqrt n))

    所以这样的话复杂度就被压到了(O(nsqrt n)),顺便提一下这种神奇的莫队方法叫做回滚莫队,不过还是比较好理解的

    CODE

    #include<cstdio>
    #include<cctype>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define RI register int
    #define CI const int&
    #define Tp template <typename T>
    using namespace std;
    typedef long long LL;
    const int N=100005;
    int blk[N]; struct ques
    {
    	int l,r,id;
    	inline ques(CI L=0,CI R=0,CI Id=0)
    	{
    		l=L; r=R; id=Id;
    	}
    	inline friend bool operator <(const ques& A,const ques& B)
    	{
    		return blk[A.l]<blk[B.l]||(blk[A.l]==blk[B.l]&&A.r<B.r);
    	}
    }q[N]; int n,m,a[N],rst[N],num,now,size,bkt[N],tbkt[N]; LL ans[N],ret;
    class FileInputOutput
    {
    	private:
    		static const int S=1<<21;
    		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
    		#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
    		char Fin[S],Fout[S],*A,*B; int pt[25],Ftop;
    	public:
    		Tp inline void read(T& x)
    		{
    			x=0; char ch; while (!isdigit(ch=tc()));
    			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
    		}
    		Tp inline void write(T x)
    		{
    			if (!x) return (void)(pc('0'),pc('
    ')); RI ptop=0;
    			while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('
    ');
    		}
    		inline void Fend(void)
    		{
    			fwrite(Fout,1,Ftop,stdout);
    		}
    		#undef tc
    		#undef pc
    }F;
    inline int min(CI a,CI b)
    {
    	return a<b?a:b;
    }
    Tp inline void maxer(T& x,const T& y)
    {
    	if (y>x) x=y;
    }
    inline LL calc(CI l,CI r,LL ret=0)
    {
    	RI i; for (i=l;i<=r;++i) tbkt[a[i]]=0; for (i=l;i<=r;++i)
    	++tbkt[a[i]],maxer(ret,1LL*tbkt[a[i]]*rst[a[i]]); return ret;
    }
    inline void add(CI now)
    {
    	++bkt[a[now]]; maxer(ret,1LL*bkt[a[now]]*rst[a[now]]);
    }
    inline void solve(CI id)
    {
    	int qr=min(id*size,n),pr=qr; RI i; memset(bkt,0,sizeof(bkt));
    	for (ret=0;blk[q[now].l]==id;++now)
    	{
    		if (blk[q[now].l]==blk[q[now].r]) { ans[q[now].id]=calc(q[now].l,q[now].r); continue; }
    		while (pr<q[now].r) add(++pr); LL t=ret; for (i=q[now].l;i<=qr;++i) add(i);
    		ans[q[now].id]=ret; for (i=q[now].l;i<=qr;++i) --bkt[a[i]]; ret=t;
    	}
    }
    int main()
    {
    	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
    	RI i; for (F.read(n),F.read(m),i=1;i<=n;++i) F.read(a[i]),rst[i]=a[i];
    	sort(rst+1,rst+n+1); num=unique(rst+1,rst+n+1)-rst-1; size=(int)sqrt(n);
    	for (i=1;i<=n;++i) blk[i]=(i-1)/size+1,a[i]=lower_bound(rst+1,rst+num+1,a[i])-rst;
    	for (i=1;i<=m;++i) F.read(q[i].l),F.read(q[i].r),q[i].id=i;
    	for (sort(q+1,q+m+1),now=i=1;i<=blk[n];++i) solve(i);
    	for (i=1;i<=m;++i) F.write(ans[i]); return F.Fend(),0;
    }
    
  • 相关阅读:
    CodeForces 19D Points (线段树+set)
    FZU 2105 Digits Count
    HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
    HDU 5634 Rikka with Phi (线段树)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高 转圈游戏(暴力快速幂)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
    Java实现 蓝桥杯 算法提高VIP Substrings(暴力)
  • 原文地址:https://www.cnblogs.com/cjjsb/p/10385708.html
Copyright © 2011-2022 走看看