數據結構之單調隊列

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

發佈了110 篇原創文章 · 獲贊 8 · 訪問量 4704
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章