- 單調隊列
-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