zoukankan      html  css  js  c++  java
  • #ST表,单调栈#洛谷 5648 Mivik的神力

    题目


    分析

    考虑答案应该是一段单调不下降的序列,
    考虑预处理出每个点往后第一个大于这个点的位置,
    那么答案应该是左端点到区间内最大的位置以及这个位置到右端点的贡献
    那么区间最大的位置可以用ST表做,然后前面的贡献用后缀和,
    后面的贡献也就似乎这个位置的值乘上后面的长度,记得开long long


    代码

    #include <cstdio>
    #include <cctype>
    #include <stack>
    #define rr register
    using namespace std;
    const int N=500011; typedef long long lll; stack<int>stac;
    int n,m,two[19],lg[N],a[N],f[N][19],fa[N]; lll s[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);
    }
    signed main(){
    	n=iut(),m=iut(),two[0]=1,lg[0]=-1;
    	a[n+1]=2e9,stac.push(n+1),fa[n+1]=n+1;
    	for (rr int i=1;i<19;++i) two[i]=two[i-1]<<1;
    	for (rr int i=1;i<=n;++i) a[i]=iut(),lg[i]=lg[i>>1]+1;
    	for (rr int i=n;i;--i){
    		while (a[i]>=a[stac.top()]) stac.pop();
    		fa[i]=stac.top(),stac.push(i);
    	}
    	for (rr int i=n;i;--i) s[i]=s[fa[i]]+1ll*(fa[i]-i)*a[i];
    	for (rr int i=1;i<=n;++i) f[i][0]=i;
    	for (rr int j=1;j<19;++j)
    	for (rr int i=1;i+two[j]-1<=n;++i){
    		rr int z1=f[i][j-1],z2=f[i+two[j-1]][j-1];
    		if (a[z1]<a[z2]) f[i][j]=z2; else f[i][j]=z1;
    	}
    	rr lll lans=0;
    	for (rr int i=1;i<=m;++i,putchar(10)){
    		rr int l=(iut()^lans)%n+1,r=l+(iut()^(lans+1))%(n-l+1);
    		rr int now,z=lg[r-l+1],z1=f[l][z],z2=f[r-two[z]+1][z];
    		if (a[z1]<a[z2]) now=z2; else now=z1;
    		print(lans=s[l]-s[now]+1ll*a[now]*(r-now+1));
    	}
    	return 0;
    } 
    
  • 相关阅读:
    02、Rendering a Triangle
    [转]Unity性能优化之Draw Call
    [转]Directx11 3D空间坐标系认识
    设置让EditPlus不产生BAK文件
    深度优先搜索与广度优先搜索对比
    python多重继承新算法C3
    php的垃圾回收机制
    python脚本自动发邮件功能
    python的keyword模块
    EditPlus如何设置——自动换行
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13922598.html
Copyright © 2011-2022 走看看