HDU 5875 Function 大連網絡賽

題意,給一堆數,給你一個區間,求這個區間第一個數 模 第二個數 模 第三個數 ....模到這個區間最後一個數,最後值是多少,有多次詢問。然後很明顯的,一個數摸一個比他小的數就變小了,比他大的數,他不變,所以總是要找小的數,如果能知道一個數在他後面第一個比他小的數u,然後取模,再去找u後面比他小的第一個數,再取模,這樣子能跳過很多不用的區間。那麼問題來了,如何快速知道一個數之後第一個比他小的數呢??單調棧,ok,解決了。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>

using namespace std;
int n, m;
int next[100005];

struct node
{
	int pos;
	int val;
}a[100005], tmp;

stack<node> s;


int main(void)
{
	int T;
	scanf("%d", &T);
	for (int i = 1; i < 100005; i++)
		a[i].pos = i;
	tmp.pos = 0;
	tmp.val = 0;
	while (T--)
	{
		scanf("%d", &n);
		for (int i = 1; i <= n; i++)
			scanf("%d", &a[i].val);
		scanf("%d", &m);
		memset(::next, 0x3f3f3f3f, sizeof ::next);
		
		while (!s.empty()) s.pop();
		s.push(tmp);

		for (int i = 1; i <= n; i++)
		{
			while (s.top().val > a[i].val)
			{
				::next[s.top().pos] = i;
				s.pop();
			}
			s.push(a[i]);
		}

		int l, r;
		for (int i = 0; i < m; i++)
		{
			scanf("%d%d", &l, &r);
			int ans = a[l].val;
			for (int j = ::next[l]; j <= r; j = ::next[j])
			{
				if (ans == 1 || ans == 0) break;
				ans %= a[j].val;
			}
			printf("%d\n", ans);
		}
	}
	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章