2018 Multi-University Training Contest 3 hdu 6319 Problem A. Ascending Rating(單調棧)
阿新 • • 發佈:2018-11-10
題意
給定一個序列 a[1..n],對於每個長度為 m 的連續子區間,求出區間 a 的最大值以及從左往右掃描該區間時 a 的最大值的變化次數。
題解
滑動視窗,從左到右,維護一個單調棧,從小到大
程式碼
#include<stdio.h> #include<deque> #include<stack> #include<iostream> using namespace std; typedef long long ll; ll a[10000005]; struct node { ll num,pos; node(){} node(ll num,ll pos) { this->num=num; this->pos=pos; } }fr,ba,gg; deque<node>que; stack<node>temp; int main() { ll T; scanf("%lld",&T); while(T--) { while(!que.empty())que.pop_back(); ll ansA=0,ansB=0,mod; ll n,m,k,p,q,r; scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&m,&k,&p,&q,&r,&mod); for(ll i=1;i<=n;i++) { if(i<=k)scanf("%lld",&a[i]); else a[i]=(a[i-1]*p+q*i+r)%mod; if(que.empty()||que.front().num<a[i])que.push_front(node(a[i],i)); while(que.size()) { ba=que.back(); if(i-ba.pos+1<=m)break; gg=que.back(); que.pop_back(); } ll ma=que.empty()?i:que.back().pos-1; for(ll j=max(i-m+1,1ll);j<=ma;j++) if(temp.empty()||temp.top().num<a[j]) temp.push(node(a[j],j)); while(!temp.empty()) que.push_back(temp.top()),temp.pop(); if(i>=m) { ansA+=que.front().num^(i-m+1); ansB+=que.size()^(i-m+1); } } printf("%lld %lld\n",ansA,ansB); } }