[POJ2823]Sliding Window(单调队列)

    xiaoxiao2021-03-25  160

    题目链接:

    http://poj.org/problem?id=2823

    题意:

    给你一个序列a,要找到两个序列 a的下标为i,i+1,i+2, ….. i+k-1 当中的最小值为b[i]; c[i]就是最大值

    题解:

    单调队列,紫书中第八章的滑动窗口。。

    优先队列也可做

    代码:

    #include <iostream> #include <cstdio> #include <cstring> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 1e6+10; struct node{ int x,y; }v[maxn]; int n,k; int a[maxn],mi[maxn],mx[maxn]; void getmin(){ int head=1,tail=0; for(int i=1; i<k; i++){ while(head<=tail && a[i]<=v[tail].x) tail--; tail++; v[tail].x=a[i],v[tail].y=i; } for(int i=k; i<=n; i++){ while(head<=tail && a[i]<=v[tail].x) tail--; // 插入到第一个比a[i]小的下一个位置,并把无用的【不可能出现在答案里的值,如果后面的一个位置比这个位置的值小,那么肯定要小的】删除 tail++; v[tail].x=a[i],v[tail].y=i; while(head<=tail && i-k+1>v[head].y) head++; // 删除队首,已经不再这个窗口里的元素 mi[i-k+1] = v[head].x; } } void getmax(){ int head=1,tail=0; for(int i=1; i<k; i++){ while(head<=tail && a[i]>=v[tail].x) tail--; tail++; v[tail].x=a[i],v[tail].y=i; } for(int i=k; i<=n; i++){ while(head<=tail && a[i]>=v[tail].x) tail--; tail++; v[tail].x=a[i],v[tail].y=i; while(head<=tail && i-k+1>v[head].y) head++; mx[i-k+1] = v[head].x; } } int main(){ cin >> n >> k; for(int i=1; i<=n; i++) a[i] = read(); getmin(); getmax(); cout << mi[1]; for(int i=2; i<=(n-k+1); i++) cout << " " << mi[i]; cout << endl; cout << mx[1]; for(int i=2; i<=(n-k+1); i++) cout << " " << mx[i]; cout << endl; return 0; }

    优先队列的写法

    #include <iostream> #include <cstdio> #include <cstring> #include <queue> #include <vector> using namespace std; typedef long long ll; #define MS(a) memset(a,0,sizeof(a)) #define MP make_pair #define PB push_back const int INF = 0x3f3f3f3f; const ll INFLL = 0x3f3f3f3f3f3f3f3fLL; inline ll read(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ////////////////////////////////////////////////////////////////////////// const int maxn = 1e6+10; int a[maxn],mi[maxn],mx[maxn]; struct node1{ int i; bool operator<(const node1& rhs) const{ return a[i]>a[rhs.i]; } }; struct node2{ int i; bool operator<(const node2& rhs) const{ return a[i]<a[rhs.i]; } }; priority_queue<node1> q1; priority_queue<node2> q2; int main(){ int n,k; scanf("%d%d",&n,&k); for(int i=1; i<=n; i++) a[i] = read(); for(int i=1; i<k; i++){ q1.push(node1{i}); q2.push(node2{i}); } int cnt1=0,cnt2=0; for(int i=k; i<=n; i++){ q1.push(node1{i}); q2.push(node2{i}); while(i-q1.top().i >= k) q1.pop(); mi[cnt1++] = a[q1.top().i]; while(i-q2.top().i >= k) q2.pop(); mx[cnt2++] = a[q2.top().i]; } for(int i=0; i<cnt1; i++){ cout << mi[i]; if(i==cnt1-1) cout << endl; else cout << " "; } for(int i=0; i<cnt2; i++){ cout << mx[i]; if(i==cnt2-1) cout << endl; else cout << " "; } return 0; }
    转载请注明原文地址: https://ju.6miu.com/read-5059.html

    最新回复(0)