HUD 3706 单调队列简单题

Problem Description

Give you three integers n, A and B.

Then we define Si = Ai mod B and Ti = Min{ Sk | i-A <= k <= i, k >= 1}

Your task is to calculate the product of Ti (1 <= i <= n) mod B.

不描述题意了,三行英文挺明了的,今天刚学单调队列,自己模拟一下过了这题

单调队列

1,永远保持队首元素为最小值。

2,插入时,先将队尾大于插入值的元素删去

3,保证队首元素一直是合法,所需元素。

代码

#include<stdio.h>

#include<math.h>

int tou, wei, count;

struct cc

{

__int64 value;

int num;

}mark[10000005];

void add ( int x ,int k)

{

if(k == 1)  return;

if( tou == wei )  {mark[tou].value = x; mark[wei].num = k; return;}

if(mark[tou].value > x) {mark[tou].value = x; mark[tou].num = k; wei = tou+1; return;}

for(int i = wei - 1; i >= tou; i--)

{

if(mark[i].value <= x)

{

mark[i+1].value = x;

mark[i+1].num = k;

wei = i + 2;

break;

}

}

for(int i = tou; i < wei; i++)

{

if(mark[i].num < count)

{

tou++;

}

else break;

}

}

int main()

{

int n, a, b;

__int64 k;

__int64 sum, ji;

while(scanf("%d%d%d", &n, &a, &b) != EOF)

{

count = -1, ji = 1;

mark[0].value = a % b;

mark[0].num = 1;

tou = 0, wei = 1, k = 1;

for(int i = 1; i <= n; i++)

{

k = k * a % b;

count = i - a;

add(k, i);

ji *= mark[tou].value;

if( ji >= b ) ji %= b;

}

printf("%I64d\n", ji);

}

}

时间: 2024-12-17 11:30:06

HUD 3706 单调队列简单题的相关文章

hdu 3706 单调队列水题

#include<stdio.h> #include<string.h> #include<iostream> using namespace std; int num[1000001],id[1000001]; int main() { int n,A,B; int i,j; while(~scanf("%d%d%d",&n,&A,&B)) { int front=0; int top=0; __int64 x=1,sum=

Sliding Window POJ - 2823 单调队列模板题

Sliding Window POJ - 2823 单调队列模板题 题意 给出一个数列 并且给出一个数m 问每个连续的m中的最小\最大值是多少,并输出 思路 使用单调队列来写,拿最小值来举例 要求区间最小值 就是维护一个单调递增的序列 对于样例 8 3 1 3 -1 -3 5 3 6 7 我们先模拟一遍 1.队列为空 1 进队 队列:1 2.3>队尾元素 3 进队 队列: 1 3 3.-1小于队尾元素,一直从尾部出队知道找到比-1小的元素或者队列为空 队列:-1 当队列中元素大于m的时候从队头删

hdu 3530 单调队列水题

给你一个数列找到最长的子序列   中的最大值减最小值值m   k之间 建立两个单调队列   一个递增    一个递减    当两个队首满足情况是就进行比较 找到最大值 当不满足是旧的移动队首      怎样移??? 移动队首id较小的一个 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; int max(int a,int b) { return a>b?a:b

poj 2823 单调队列裸题

两个队列分别维持最大和最小 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; struct node { int mi,ma; }num[1000010]; int sax[1000010],sin[1000010]; int ida[1000010],idi[1000010]; int main() { int n,m,i,j,k,a; while(~scanf(&

单调队列水题 刷广告

[问题描述] 最近,afy决定给TOJ印刷广告,广告牌是刷在城市的建筑物上的,城市里有紧靠着的N个建筑. afy决定在上面找一块尽可能大的矩形放置广告牌.我们假设每个建筑物都有一个高度, 从左到右给出每个建筑物的高度H1,H2-HN,且0<Hi<=1,000,000,000,并且我们假设每个建筑物的宽度均为1. 要求输出广告牌的最大面积. [输入文件] 输入文件 ad.in 中的第一行是一个数n (n<= 400,000) 第二行是n个数,分别表示每个建筑物高度H1,H2-HN,且0&l

poj2823_单调队列简单入门

题目链接:http://poj.org/problem?id=2823 #include<iostream> #include<cstdio> #define M 1000001 using namespace std; int n,k; int a[M]; int q[M]; int p[M]; void get_min() { int head=1; int tail=0; for(int i=0;i<k-1;i++) { while(head<=tail&

单调队列————[USACO09MAR]向右看齐Look Up

先了解一下单调队列: 很明显的具有单调性 分为单调递增和单调递减两种,简单点讲就是维护队头为最大值或者为最小值 (建议采用双向队列  比较好写) 具体步骤:(这个是单调递减) 如果队列非空且当前值比队尾元素大,不断删除比该值小的元素,否则直接队尾入队 while(!que.empty()&&ma[i]>que.back()) {     que.pop_back(); } que.push_back(i); 单调队列的作用:: 1):可以用来维护区间的单调性,用来解决最大或最小的问题

【单调队列】POJ2823-Sliding Window

单调队列经典题之一. [思路] 设置两个单调队列分别记录最大值和最小值.对于每一个新读入的数字,进行两次操作(对于求最大值和最小值中的某一个而言),一是若队首不在滑窗范围内则删去:二是删去队末比当前值小(或大)的值,并将当前值插入对尾.每一次的最小(大)值就是当前单调队列的队首. [错误点] 一定要写while (scanf("%d%d",&n,&k)!=EOF),否则会WA. 我一开始的做法是这样的:先把第一个数插入队尾,再从第二个数开始进行后续操作.这样的问题在于如

hdu3415(单调队列)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3415 题意:一个长度为n包含正负整数的数环,即第1个的左边是第n个.从中选一个不超过k的序列,使得序列和最大,最大值相同选开始点最小的,开始点相同选长度最小的. 分析:单调队列维护在k个数之内的最小值的下标,然后一直扫一遍就行了,只要懂单调队列这题就是水题了. #include <cstdio> #include <cstring> #include <cmath> #in