BZOJ 1012 线段树或单调队列

1012: [JSOI2008]最大数maxnumber

题意:两种操作:1、查询当前数列中末尾L个数中的最大的数;2、当前数列末尾插入一个数。

tags:水题

线段树

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2e5+10;
const ll inf=1e18;

int M, k;
ll D, tr[N<<2], t;
void updata(int ro, int L, int R, int p, ll x)
{
    if(L==R && L==p) { tr[ro]=(tr[ro]+x)%D; return ; }
    int mid=L+((R-L)>>1);
    if(p<=mid) updata(ro<<1, L, mid, p, x);
    else updata(ro<<1|1, mid+1, R, p, x);
    tr[ro]=max(tr[ro<<1], tr[ro<<1|1]);
}
ll query(int ro, int L, int R, int l, int r)
{
    if(L==l && R==r) return tr[ro];
    int mid=L+((R-L)>>1);
    if(r<=mid) return query(ro<<1, L, mid, l, r);
    else if(mid<l) return query(ro<<1|1, mid+1, R, l, r);
    else return max(query(ro<<1, L, mid, l, mid), query(ro<<1|1, mid+1, R, mid+1, r));
}
int main()
{
    scanf("%d %lld", &M, &D);
    ll x;
    char ch[10];
    FF(i,1,M) {
        scanf("%s %lld", ch, &x);
        if(ch[0]==‘A‘) updata(1, 1, M, k+1, x+t), k++;
        else {
            t=query(1, 1, M, k-x+1, k);
            printf("%lld\n", t);
        }
    }

    return 0;
}

单调队列  感觉单调队列比较玄。   注:单调队列一般在数列一端有最大(最小)比较的时候用。

#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define FF(i,a,b) for (int i=a;i<=b;i++)
#define F(i,b,a)  for (int i=b;i>=a;i--)
#define mes(a,b)  memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
typedef long long ll;
const int N = 2e5+10;

int M, k;
ll D, a[N], mx[N], t;
int main()
{
    scanf("%d %lld", &M, &D);
    char ch[10];
    ll x;
    FF(cas,1,M) {
        scanf("%s %lld", ch, &x);
        if(ch[0]==‘A‘) {
            a[++k]=(x+t)%D;
            F(i,k,0) {
                if(mx[i]<a[k]) mx[i]=a[k];
                else break;
            }
        }
        else printf("%lld\n", t=mx[k-x+1]);
    }

    return 0;
}

时间: 2024-12-22 12:11:28

BZOJ 1012 线段树或单调队列的相关文章

BZOJ 1012 线段树||单调队列

非常裸的线段树  || 单调队列: 假设一个节点在队列中既没有时间优势(早点入队)也没有值优势(值更大),那么显然不管在如何的情况下都不会被选为最大值. 既然它仅仅在末尾选.那么自然能够满足以上的条件. 线段树 #include "stdio.h" #include "string.h" struct node { int l,r,Max; }data[800010]; int Max(int a,int b) { if (a<b) return b; els

BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树/树状数组/乱搞

1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 4750  Solved: 2145[Submit][Status][Discuss] Description 现 在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度. 2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一

ZOJ 3632 Watermelon Full of Water(dp+线段树或单调队列优化)

Watermelon Full of Water Time Limit: 3 Seconds      Memory Limit: 65536 KB Watermelon is very popular in the hot summer. Students in ZJU-ICPC Team also love watermelon very much and they hope that they can have watermelon to eat every day during the

Luogu4085 [USACO17DEC]Haybale Feast (线段树,单调队列)

\(10^18\)是要long long的. \(nlogn\)单调队列上维护\(logn\)线段树. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #define R(a,b,c) for(register int a = (b); a <= (c); ++ a) #define nR(a,b,c

bzoj 1171 并查集优化顺序枚举 | 线段树套单调队列

详见vfleaking在discuss里的题解. 收获: 当我们要顺序枚举一个序列,并且跳过某些元素,那么我们可以用并查集将要跳过的元素合并到一起,这样当一长串元素需要跳过时,可以O(1)跳过. 暴力: 1 /************************************************************** 2 Problem: 1171 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:1908 ms 7

PKU 2823 Sliding Window(线段树||RMQ||单调队列)

#include<cstdio> #include<algorithm> #define maxn 1000005 #define inf 0x3f3f3f3f using namespace std; int Segtree_min[maxn<<2],Segtree_max[maxn<<2]; int n,k,value; int begin,end; //每个结点保存该区间线段的最大/小值 void Build(int l,int r,int pos)

bzoj 1758 [Wc2010]重建计划 分数规划+树分治单调队列check

[Wc2010]重建计划 Time Limit: 40 Sec  Memory Limit: 162 MBSubmit: 4345  Solved: 1054[Submit][Status][Discuss] Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai,Bi,Vi分别表示道路(Ai,Bi),其价值为Vi 其中城市由1..N

BZOJ 4262 线段树+期望

思路: 把询问离线下来,查询max和查询min相似,现在只考虑查询max 令sum[l,r,x]表示l到r内的数为左端点,x为右端点的区间询问的答案 那么询问就是sun[l1,r1,r2]-sum[l1,r1,l1-1] 从1到n枚举x,维护区间线段树表示sum[l,r,x],发现从x-1转移到x的过程中,每个数加上了max(a[pos]..a[x])的答案. 用单调队列维护一个单调递减的序列,由于a数列是随机的,这个队列期望有log个元素,所以只需要对这log段暴力修改,复杂度nlog^2n

bzoj 1293: [SCOI2009]生日礼物【单调队列】

一开始用了复杂度看起来对实则常数巨大的线段树+hash--后来发现队列就行-- 把珠子按位置排序,然后用队列维护一段,枚举右端点更新答案即可 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; const int N=1000005,inf=2147483647; int n,m,s[65],ans=inf,tot,sum,l=1,r; struct qwe { int