• 【UOJ UNR #1】争夺圣杯


    来自FallDream的博客,未经允许,请勿转载,谢谢。


    传送门

    考虑直接对每个数字,统计它会产生的贡献。

    单调栈求出每个数字左边第一个大等于他的数,右边第一个大于他的 (注意只能有一边取等)

    假设左右两边分别有x1,x2个数,较大的是mx,较小的是mn

    对于长度在(mx+1,mn+mx+1]的x,会产生mn+mx+1 - x - 1的贡献

    对于长度在(mn,mx+1]的数,会产生 mn+1的贡献

    对于长度在[1,mn]中的数x,会产生x的贡献。

    差分维护即可

    #include<iostream>
    #include<cstdio>
    #define MN 1000000
    #define mod 998244353
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int n,a[MN+5],s[MN+5],g[MN+5],top=0,q[MN+5],Lt[MN+5],Rt[MN+5],ans=0;
    inline void R(int&x,int y){x+=y;x>=mod?x-=mod:0;}
    int main()
    {
        n=read();
        for(int i=1;i<=n;++i) a[i]=read();
        for(int i=1;i<=n;++i) 
        {
            while(top&&a[i]>=a[q[top]]) --top;
            Lt[i]=q[top]+1;q[++top]=i;
        }
        q[top=0]=n+1;
        for(int i=n;i;--i) 
        {
            while(top&&a[i]>a[q[top]]) --top;    
            Rt[i]=q[top]-1;q[++top]=i;
        }
        for(int i=1;i<=n;++i)
        {
            int mn=min(i-Lt[i],Rt[i]-i),y=mod-(a[i]%mod),mx=max(i-Lt[i],Rt[i]-i),z=a[i]%mod;
            if(mn>0) R(s[1],z),R(s[mn+1],y);
            R(g[mn+1],1LL*(mn+1)*z%mod),R(g[mx+2],1LL*(mod-mn-1)*z%mod);
            R(g[mx+2],1LL*(mn+mx+2)*z%mod);R(s[mx+2],y);
            R(g[mn+mx+2],1LL*(mod-mn-mx-2)*a[i]%mod);R(s[mn+mx+2],z);
        }
        for(int i=1;i<=n;++i)
        {
            R(g[i],g[i-1]);R(s[i],s[i-1]);    
            ans^=(1LL*s[i]*i+g[i])%mod;
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    [转]HSPICE 使用流程
    [转]到底怎么样才叫看书?——上篇
    js弹出层
    mvc自定义扩展控件
    yield 关键字
    mvc学习地址
    C# 将List中的数据导入csv文件中
    Asp.net 下载文件(弹出对话框的形式)
    Asp.net中用Jquery实现Ajax回调后台方法
    SharePoint中获取当前登录的用户名
  • 原文地址:https://www.cnblogs.com/FallDream/p/uoj213.html
Copyright © 2020-2023  润新知