- 单调队列
-A - Subsequence
-B - Largest Rectangle in a Histogram
-C - Second My Problem First
-D - Alice’s mooncake shop
-G - Queue CodeForces - 91B
-I - Cornfields POJ - 2019
https://blog.csdn.net/qq_40871466/article/details/97413921
A - Subsequence
https://www.cnblogs.com/648-233/p/11156168.html 最近真的是疯狂写bug我也是醉了。先是用queue然后下面有个地方是要从前往后回溯的不能pop要pop_front所以只能用deque还找了好一会。然后getminngetmax的while又循环找了好久。然后初始化。最后发现不能简单地pop之前的数据还会影响后面。这个不是有区间限制的那种题。自闭。乖乖用数组写。喵了个咪的。正解不放了,看连接。双端队列ac的。最后是我第二次写的 这道题第二次写的时候对第一次已经基本没有印象。今天跟朋友聊天觉得自己学习有很大的方法问题。没有认真思考算法,每次只看一道题。这是不对的,所以有把之前的题领出来做,接下来说下我第二次写的感受。 首先已经知道这是单调队列了。 所以就想存一个最大值一个最小值。后来发现不能只调整尾部。差值大于k就需要调整头部了,否则最大值或最小值一直不变或者变得更大 而调整头部需要判断是决定最大值(最小)要变小(大),head往后缩,结论是谁坐标在前面谁变(不解释思考一下)所以原本在队列里村的是值,现在只能存坐标了 简单来讲就这两个坑点。 有一个点不明白。为什么是 index=haha1[ head1++]; 不是 head1++; index=haha1[ head1++];自己写的
#include<iostream>
#include <algorithm>
using namespace std;
const int maxn=100000+5;
int main()
{
int a[maxn];
int haha1[maxn],haha2[maxn];
int n,m,k;
while(cin>>n>>m>>k) {
int head1 = 0, head2 = 0, tail1 = 0, tail2 = 0, index = 0, maxx = 0;
for (int i = 1; i <= n; i++) {
cin >> a[i];
while (head1 < tail1 && a[i] <a[ haha1[tail1 - 1]])tail1--;
haha1[tail1++] = i;
while (head2 < tail2 && a[i] >a[ haha2[tail2 - 1]])tail2--;
haha2[tail2++] = i;
int e = a[haha2[head2]] - a[haha1[head1]];
// cout<<e<<haha2[head2]<<haha1[head1]<<endl;
while(head1<tail1&&head2<tail2&&e>k){
if(haha1[head1]<haha2[head2]){
index=haha1[ head1++];
}
else {
index=haha2[head2++];
}
e = a[haha2[head2]] - a[haha1[head1]];
}
if (head1<tail1&&head2<tail2&&e >= m ){
maxx = max(maxx, i-index);
}
}
cout << maxx << endl;
}
}
(好像错了)双端
#include <cstdio>
#include <queue>
using namespace std;
const int N = 1000005;
typedef pair<int,int> P;
deque<P> Q1;
deque<P> Q2;
int ans1[N],ans2[N];
int main ()
{
int n,k,x,i;
while (~scanf("%d%d",&n,&k))
{
while (!Q1.empty()) Q1.pop_back();
while (!Q2.empty()) Q2.pop_back();
for (i=0;i<n;i++)
{
scanf("%d",&x);
while (!Q1.empty() && Q1.back().first >= x)
Q1.pop_back();
Q1.push_back(P(x,i));
while (!Q1.empty() && Q1.front().second <= i-k)
Q1.pop_front();
ans1[i] = Q1.front().first;
while (!Q2.empty() && Q2.back().first <= x)
Q2.pop_back();
Q2.push_back(P(x,i));
while (!Q2.empty() && Q2.front().second <= i-k)
Q2.pop_front();
ans2[i] = Q2.front().first;
}
for (i=k-1;i<n;i++)
printf(i==n-1?"%d\n":"%d ",ans1[i]);
for (i=k-1;i<n;i++)
printf(i==n-1?"%d\n":"%d ",ans2[i]);
}
return 0;
}
B - Largest Rectangle in a Histogram
思路基本是对的,写挫了。下次重写一遍。以下为优秀代码(感觉都不用单调队列思想https://blog.csdn.net/SSL_hzb/article/details/81697717
#include<cstdio>
#include<algorithm>
using namespace std;
int n,a,b,stack[100001],len,w[100001],s;
long long ans;
int main()
{
while (scanf("%d",&n),n)
{
len=ans=0;
for (int i=1;i<=n+1;i++)
{
if (i!=n+1) scanf("%d",&a);
else a=0;//最后没有一个递减的来更新答案,所以枚举到n+1的时候弄一个很小的值
if (a>stack[len])
{
stack[++len]=a;
w[len]=1;
}
else
{
s=0;
while (a<stack[len])
{
s+=w[len];
ans=max(ans,(long long)s*stack[len]);//更新答案
len--;
}
stack[++len]=a;w[len]=s+1;//新加入一个削掉多余部分的矩形
}
}
printf("%lld\n",ans);
}
}
之前代码就不放上来了原本有个地方写错了。但是问题是超时不管了下次再写一遍
C - Second My Problem First
根据题解写的数组。但是这个用que感觉简单。第二遍写的时候发现不难,就是num不要特地去求会超时真的最近傻到爆ai。#include<iostream>
#include <queue>
using namespace std;
int mod;
struct yyy{
int val,i;
yyy(int a,int c):val(a),i(c){}
};
deque<yyy>que;
void init(){
while(!que.empty())que.pop_back();
}
int main()
{
int n,m;
while(~scanf("%d%d%d",&n,&m,&mod)) {
long long ans = 1,num=1;
init();
for (int i = 1; i <= n; i++) {
num =num*m%mod;
// cout<<num<<endl;
while (!que.empty() && i - que.back().i > m)que.pop_front();
while (!que.empty() && num < que.back().val)que.pop_back();
que.push_back(yyy(num,i));
ans = ans * que.front().val % mod;
}
cout << ans << endl;
}
}
D - Alice's mooncake shop
#include<iostream>
#include <queue>
using namespace std;
struct node{
int valnum,hour;
node(int x,int y):valnum(x),hour(y){}
};
//string mon[20]={"","Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};
//int d[20]={0,31,28,31,30,31,30,31,31,30,31,30,31};
string mon[20]={"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov","Dec"};
int d[20]={0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
string M;
deque<node>cost;
queue<node>order;
void init(){
while(!cost.empty())cost.pop_back();
while(!order.empty())order.pop();
}
int main() {
int n, m;
while (~scanf("%d%d", &n, &m) && (n || m)) {
init();
for (int i = 0; i < n; i++) {
cin >> M;
int day, year, hour, num;
scanf("%d%d%d%d", &day, &year, &hour, &num);
for (int j = 2000; j < year; j++) {
if (( j % 4 == 0 && j % 100) || j % 400 == 0)day += 366;
else day += 365;
}
int j;
for (j = 1; j <= 12; j++)
if (M == mon[j])break;
for (int k = 1; k < j; k++) {
if (k == 2 && (( year % 4 == 0 && year % 100) || year % 400 == 0))
day += 29;
else day += d[k];
}
day--;
order.push(node(num, day * 24 + hour));
}
int T, S;
scanf("%d%d", &T, &S);
long long ans = 0;
for (int i = 0; i < m; i++) {
int x;
scanf("%d", &x);
while (!cost.empty() && x <= cost.back().valnum + (i - cost.back().hour) * S) {
cost.pop_back();
}
cost.push_back(node(x, i));
while (!order.empty() && i == order.front().hour) {
while (!cost.empty() && i - order.front().hour > T)cost.pop_front();
ans += (cost.front().valnum + (i - cost.front().hour) * S) * order.front().valnum;
order.pop();
}
}
printf("%lld\n", ans);
}
}
G - Queue CodeForces - 91B
疯狂读错题,开始以为写过,后来发现基本不一样也是醉了,一改再改后面发现思路不行。 写法样例能过但是数据庞大不可实现为了纪念改了那么久bug还是给放下吧#include<iostream>
const int MAXM=50000;
int a[MAXM+5],s[MAXM+5],st[(MAXM<<2)+5];
#include <string.h>
using namespace std;
void build(int o,int l,int r){
if(l==r)st[o]=0;
else{
int m=l+((r-l)>>1);
build(o<<1,l,m);
build((o<<1)|1,m+1,r);
st[o]=max(st[o<<1],st[(o<<1)|1]);
}
}
void update(int o,int l,int r,int ind,int ans){
if(l==r){
st[o]=ans;
// cout<<l<<ans<<endl;
return;
}
int m=l+((r-l)>>1);
if(ind<=m){
update(o<<1,l,m,ind,ans);
}
else{
update((o<<1)|1,m+1,r,ind,ans);
}
st[o]=max(st[o<<1],st[(o<<1)|1]);//递归回之后用儿子结点更新父节点(此处是区间最大值)
}
int query(int o,int l,int r,int ql,int qr){
// cout<<l<<" "<<r<<ql<<qr<<endl;
if(ql>r||qr<l) return 0;
if(ql<=l&&qr>=r) {
// cout<<l<<" "<<r<<ql<<qr<<endl;
return st[o];}
int m=l+((r-l)>>1);
int p1=query(o<<1,l,m,ql,qr),p2=query((o<<1)|1,m+1,r,ql,qr);
return max(p1,p2);
}
int main()
{
int n;cin>>n;
build(1,1,100);
for(int i=0;i<n;i++){
cin>>a[i];
}
for(int i=n-1;i>=0;i--) {
update(1, 1, 100, a[i], i);
// cout<<query(1,1,100,1,10)<<endl;
s[i]=query(1,1,100,1,a[i]-1)-i-1;
}
for(int i=0;i<n;i++) {
if (s[i] >= 0)cout << s[i] << endl;
else cout << -1 << endl;
}
}
https://blog.csdn.net/a664607530/article/details/52909700
Queue
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf (-((LL)1<<40))
#define lson k<<1, L, (L + R)>>1
#define rson k<<1|1, ((L + R)>>1) + 1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
#define dec(i, a, b) for(int i = a; i >= b; i --)
#define rmq_log2(x,val) while((1<<(x+1))<=val)x++;
template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b; }
typedef long long LL;
const int maxn =2e5+5;
const int MAXM = 110000;
const double eps = 1e-8;
LL MOD = 1000000007;
int n,k;
int a[maxn],dp[maxn][20];
void rmq_init()
{
for(int i=1;i<=n;i++)
dp[i][0]=a[i];//初始化
for(int j=1;(1<<j)<=n;j++)
for(int i=1;i+(1<<j)-1<=n;i++)
dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
}
int rmq(int l,int r)
{
int k=0;
rmq_log2(k,r-l+1)
return max(dp[l][k],dp[r-(1<<k)+1][k]);
}
int solve(int num){
int ans=0;
int x=n/num;
// int flag=0;
// if(num==1)flag=1;
for(int i=1;i<=num;i++){
ans+=rmq((i-1)*x+1,i*x);
// if(flag)cout<<ans<<endl;
if(ans>k) return 1;
}
if(ans>k)return 1;
else return 0;
}
int main()
{
while(cin>>n>>k&&!(n==-1&&k==-1)) {
int sum=0,flag=0;
rep(i, 1, n) {
cin >> a[i];
sum += a[i];
if (a[i] >= k)flag = 1;
}
if (flag == 1){cout << 1 << endl;continue;}
if (sum < k){cout << -1 << endl;continue;}
rmq_init();
int l = 1, r = n;/*l=2*/
int answ,mid;
while (l <= r) {/*l<r*/
int mid = (l + r) / 2;
// cout<<mid<<endl;
if (solve(mid)) {//这里传的是组的个数
r = mid - 1;/*l=mid+1*/
answ = mid;
// cout<<mid<<endl;
} else l = mid + 1;
}
cout << answ << endl;/*n/answ*/
}
}
I - Cornfields POJ - 2019
250*250直接暴力一下。scanf真好。cin会超时。#include <stdio.h>
#include <algorithm>
const int inf=10000000;
using namespace std;
int main()
{
int bigedge,smalledge,coun;
scanf("%d%d%d",&bigedge,&smalledge,&coun);
int a[300][300],f[300][270];
for(int i=1;i<=bigedge;i++)
for(int j=1;j<=bigedge;j++){
scanf("%d",&a[i][j]);
}
while(coun--){
int x,y;
scanf("%d%d",&x,&y);
if(!f[x][y]){
int minn=inf,maxx=0;
for(int i=x;i<x+smalledge;i++)
for(int j=y;j<y+smalledge;j++){
minn=min(a[i][j],minn);
maxx=max(a[i][j],maxx);
}
f[x][y]=maxx-minn;
}
printf("%d\n",f[x][y]);
}
}
学习st算法二级rmq算法。
记忆化搜索https://blog.csdn.net/hjf1201/article/details/78680814