HDU 6319 Ascending Rating 單調佇列,(最大值變化次數)
阿新 • • 發佈:2018-11-02
題意:長度為n的序列a.對每個m大小的區間[i,i+m-1],求出該區間的最大值,以及最大值變化的次數.
例如區間(4,2,7,5),最大值變化次數為2. n<=1e7.
n<=1e7. 標準解應該為O(n). 容易想到用單調佇列維護每個區間的最大值.
發現正著做單調佇列的過程中,單調佇列的大小 是從右往左數 最大值的變化次數.
例如區間(4,2,7,5,1,3) 單調佇列中存的為(7,5,3) 因為每次加入一個數 會把前面比它小的彈出.
那麼逆著做一遍單調佇列即可.
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e7+5; int n,m,k,p,q,r,mod,T,a[N]; int deq[N],front,tail; int main(){ scanf("%d",&T); while(T--){ scanf("%d%d%d%d%d%d%d",&n,&m,&k,&p,&q,&r,&mod); for(int i=1;i<=k;i++) scanf("%d",&a[i]); for(int i=k+1;i<=n;i++) a[i]=(1ll*a[i-1]*p+1ll*q*i+r)%mod; ll A=0,B=0,tail=0,front=0; for(int i=n;i>=1;i--){ while(front<tail && deq[front]>i+m-1) front++; while(front<tail && a[deq[tail-1]]<=a[i]) tail--; deq[tail++]=i; if(i>n-m+1) continue; int mx=a[deq[front]],cnt=tail-front; A=A+(mx^i),B=B+(cnt^i); } printf("%I64d %I64d\n",A,B); } return 0; }