1. 程式人生 > >uoj#213. 【UNR #1】爭奪聖杯

uoj#213. 【UNR #1】爭奪聖杯

全部 tar while span -i long col read pro

http://uoj.ac/problem/209

單調棧求出每個位置x左邊第一個大於它的位置L[x]和右第一個不小於它的位置R[x],於是矩形L[x]<=l<=x<=r<=R[x]內的點(l,r)對應的區間[l,r]的最值為x位置的值,這個矩形內的點只對答案數組的二階差分的四個位置有影響,可以全部統計後再求兩次前綴和得到答案。

#include<bits/stdc++.h>
typedef long long i64;
const int N=1e6+7,P=998244353;
char ib[N*13],*ip=ib;
int _(){
    
int x=0; while(*ip<48)++ip; while(*ip>47)x=x*10+*ip++-48; return x; } int n,a[N],ss[N],ls[N],rs[N],sp=0; i64 s[N]; int main(){ fread(ib,1,sizeof(ib),stdin); n=_(); for(int i=1;i<=n;++i)a[i]=_(); a[0]=a[n+1]=0x7fffffff; for(int i=1;i<=n+1;++i){
while(sp&&a[ss[sp]]<a[i])rs[ss[sp--]]=i-1; ss[++sp]=i; } sp=0; for(int i=n;i>=0;--i){ while(sp&&a[ss[sp]]<=a[i])ls[ss[sp--]]=i+1; ss[++sp]=i; } for(int i=1;i<=n;++i){ int x=i-ls[i]+1,y=rs[i]-i+1; if(x>y)std::swap(x,y); s[
0]+=a[i]; s[x]-=a[i]; s[y]-=a[i]; s[x+y]+=a[i]; } s[0]%=P; for(int i=1;i<n;++i)(s[i]+=s[i-1])%=P; for(int i=1;i<n;++i)(s[i]+=s[i-1])%=P; int ans=0; for(int i=0;i<n;++i)ans^=s[i]<0?s[i]+P:s[i]; printf("%d\n",ans); return 0; }

uoj#213. 【UNR #1】爭奪聖杯