1. 程式人生 > >HDU 6319 Problem A. Ascending Rating(單調隊列)

HDU 6319 Problem A. Ascending Rating(單調隊列)

type typedef ++ ems 區間 tor gif i++ lose

要求一個區間內的最大值和每次數過去最大值更新的次數,然後求每次的這個值異或 i 的總和。

這個序列一共有n個數,前k個直接給出來,從k+1到n個數用公式計算出來。

因為要最大值,所以就要用到單調隊列,然後從後往前掃一遍然後每次維護遞減的單調隊列。

先把從n-m+1以後開始的數放進單調隊列,這時候先不操作,然後剩下的數就是要異或相加的數,然後每次的隊首元素就是這個區間內的最大值,這個隊列裏的元素個數,其實就是更新到最大值的逆過程,也就是最大值需要更新的次數。

技術分享圖片
#include<map>
#include<set>
#include<ctime>
#include
<cmath> #include<stack> #include<queue> #include<string> #include<vector> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define lowbit(x) (x & (-x)) typedef unsigned long long int
ull; typedef long long int ll; const double pi = 4.0*atan(1.0); const int inf = 0x3f3f3f3f; const int maxn = 10000100; const int maxm = 1000005; using namespace std; int T, tol; int n, m; ll a[maxn]; int que[maxn]; void init() { memset(a, 0, sizeof a); } int main() { scanf("%d", &T);
while(T--) { int k; int p, q, r, mod; scanf("%d%d%d%d%d%d%d", &n, &m, &k, &p, &q, &r, &mod); for(int i=1; i<=k; i++) scanf("%lld", &a[i]); for(int i=k+1; i<=n; i++) a[i] = (1ll*p*a[i-1] + 1ll*q*i + r) % mod; int head, tail; head = tail = 0; for(int i=n; i>n-m+1; i--) { while(head != tail && a[i] >= a[que[tail-1]]) tail--; que[tail++] = i; } /* for(int j=head; j<tail; j++) printf("%d %d %lld\n", i, que[j], a[que[j]]); printf("\n"); */ ll ans1 = 0; ll ans2 = 0; for(int i=n-m+1; i>=1; i--) { while(head != tail && a[i] >= a[que[tail-1]]) tail--; que[tail++] = i; while(i + m - 1 < que[head]) head++; /* for(int j=head; j<tail; j++) printf("%d %d %lld\n", i, que[j], a[que[j]]); printf("\n"); */ ans1 += (a[que[head]] ^ i); ans2 += ((tail - head) ^ i); } printf("%lld %lld\n", ans1, ans2); } return 0; }
View Code

HDU 6319 Problem A. Ascending Rating(單調隊列)