zoukankan      html  css  js  c++  java
  • [BZOJ4540][HNOI2016]序列

    BZOJ
    Luogu

    sol

    区间?可离线?顺手就掏出了莫队。
    最主要的问题就是移动区间怎么做到(O(1))更新答案。
    我们考虑由([L+1,R])移动到([L,R])
    这样一共新产生了(R-L+1)个子区间([L,L],[L,L+1]...[L,R])
    ([L,R])中最小值的位置为(P),那么上述区间中([L,P]...[L,R])的贡献就全都是(a[P])
    考虑用(sr[i])表示左端点是(i),右端点在(i)(n)之间的所有区间的最小值之和。
    那么上述中剩余的区间([L,L]...[L,P-1])的贡献就应为(sr[L]-sr[P])
    处理(sr)数组:(sr[i]=sr[nxt[i]]+(nxt[i]-i)*a[i])其中(nxt[i])表示(i)之后第一个比(a[i])小的数的位置。
    同理处理左边的(sl)数组。
    复杂度(O(nsqrt{n}+msqrt{n}))

    加一个莫队的注意事项:关于
    while(R<q[i].r)while(L>q[i].l)while(R>q[i].r)以及while(L<q[i].l)的顺序关系。
    最优的顺序就是像上面一样:右端点扩张->左端点扩张->右端点收缩->左端点收缩。不正确的处理顺序会导致左端点的位置在右端点的右边这种从而RE。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    #define ll long long
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 1e5+5;
    int n,m,block,a[N],lg[N],ST[20][N],lst[N],nxt[N],Stack[N];
    ll sl[N],sr[N],Ans,ans[N];
    struct query{
    	int l,r,id;
    	bool operator < (const query b) const
    		{return l/block<b.l/block||(l/block==b.l/block&&r<b.r);}
    }q[N];
    int Query(int l,int r)
    {
    	int k=lg[r-l+1];
    	return a[ST[k][l]]<=a[ST[k][r-(1<<k)+1]]?ST[k][l]:ST[k][r-(1<<k)+1];
    }
    int main()
    {
    	n=gi();block=sqrt(n);m=gi();lg[0]=-1;
    	for (int i=1;i<=n;++i) a[i]=gi(),ST[0][i]=i,lg[i]=lg[i>>1]+1;
    	for (int j=1;j<20;++j)
    		for (int i=1;i+(1<<j-1)<=n;++i)
    			ST[j][i]=a[ST[j-1][i]]<=a[ST[j-1][i+(1<<j-1)]]?ST[j-1][i]:ST[j-1][i+(1<<j-1)];
    	for (int i=1,top=0;i<=n;++i)
    	{
    		while (top&&a[Stack[top]]>=a[i]) --top;
    		lst[i]=Stack[top];sl[i]=sl[lst[i]]+1ll*(i-lst[i])*a[i];
    		Stack[++top]=i;
    	}
    	Stack[0]=n+1;
    	for (int i=n,top=0;i;--i)
    	{
    		while (top&&a[Stack[top]]>=a[i]) --top;
    		nxt[i]=Stack[top];sr[i]=sr[nxt[i]]+1ll*(nxt[i]-i)*a[i];
    		Stack[++top]=i;
    	}
    	for (int i=1;i<=m;++i) q[i]=(query){gi(),gi(),i};
    	sort(q+1,q+m+1);
    	int L=1,R=0;
    	for (int i=1,pos;i<=m;++i)
    	{
    		while (R<q[i].r)
    		{
    			++R;pos=Query(L,R);
    			Ans+=1ll*(pos-L+1)*a[pos]+sl[R]-sl[pos];
    		}
    		while (L>q[i].l)
    		{
    			--L;pos=Query(L,R);
    			Ans+=1ll*(R-pos+1)*a[pos]+sr[L]-sr[pos];
    		}
    		while (R>q[i].r)
    		{
    			pos=Query(L,R);
    			Ans-=1ll*(pos-L+1)*a[pos]+sl[R]-sl[pos];--R;
    		}
    		while (L<q[i].l)
    		{
    			pos=Query(L,R);
    			Ans-=1ll*(R-pos+1)*a[pos]+sr[L]-sr[pos];++L;
    		}
    		ans[q[i].id]=Ans;
    	}
    	for (int i=1;i<=m;++i) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    此心本净四——圣言录·下·平等无分别
    此心本净三——圣言录·中·空性
    一饮一啄,自成因果
    心为何而动······
    此心漂泊
    喜欢看心的幻化
    (js描述的)数据结构[集合结构](6)
    (js描述的)数据结构[双向链表](5)
    (js描述的)数据结构[链表](4)
    微信小程序(黑马优购)完成!!{10天}
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8457654.html
Copyright © 2011-2022 走看看