1. 程式人生 > 資訊 >華碩公佈 RTX 30 系移動顯示卡引數表,可知 “Max-Q”版具體功耗

華碩公佈 RTX 30 系移動顯示卡引數表,可知 “Max-Q”版具體功耗

技術標籤:筆記演算法

題目1:

設計一個支援push,pop,top等操作並且可以在O(1)時間內檢索出最小元素的堆疊。
push(x)–將元素x插入棧中
pop()–移除棧頂元素
top()–得到棧頂元素
getMin()–得到棧中最小元素

思路:

該題目中push,pop,top三個操作對於一個棧來說均可在O(1)時間內完成,而對於getMin操作則需要維護一個數組或者棧,來儲存棧中每入棧一個數時的最小值,這樣即可在O(1)時間完成getMin操作。

題目2:

你將要實現一個功能強大的整數序列編輯器。
在開始時,序列是空的。
編輯器共有五種指令,如下:
1、“I x”,在游標處插入數值x。

2、“D”,將游標前面的第一個元素刪除,如果前面沒有元素,則忽略此操作。
3、“L”,將游標向左移動,跳過一個元素,如果左邊沒有元素,則忽略此操作。
4、“R”,將游標向右移動,跳過一個元素,如果右邊沒有元素,則忽略次操作。
5、“Q k”,假設此刻游標之前的序列為a1,a2,…,an,輸出max1≤i≤kSi,其中Si=a1+a2+…+ai

輸入格式

第一行包含一個整數Q,表示指令的總數。
接下來Q行,每行一個指令,具體指令格式如題目描述。

輸出格式

每一個“Q k”指令,輸出一個整數作為結果,每個結果佔一行。

資料範圍

1≤Q≤1e6
|x|≤1e3
1≤k≤n

輸入樣例

8

I 2
I -1
I 1
Q 3
L
D
R
Q 2

輸出樣例

2
3

思路(對頂棧):

此題的四種操作都在游標位置處發生,並且操作完成後游標至多再移動一個位置,考慮到該特性,我們可以使用對頂棧來維護該序列,即游標發生移動則只需要改變對頂棧的棧頂就行,並且再用一個數組來維護游標前序列中字首和的最大值。

程式碼:

#include<iostream>
#include<stack>
#include<algorithm>
#include<climits>
using namespace std;
const int N=1000010;
int S[
N],s,summax[N];//S[N]是字首和陣列,而summax[N]是維護游標前的序列中字首和最大值的陣列 stack<int> a,b;//對頂棧 int main() { int Q,x,k; char c; cin>>Q; summax[0]=INT_MIN;//此舉很重要 while(Q--) { cin>>c; if(c=='I') { cin>>x; a.push(x); s++; S[s]=x+S[s-1]; summax[s]=max(summax[s-1],S[s]); } else if(c=='D') { if(!a.empty())//此處if判斷如果不加則會Segmentation Fault,因為如果棧已空,則再沒有元素出棧,以下if語句同理 { a.pop(); s--; } } else if(c=='L') { if(!a.empty()) { b.push(a.top()); a.pop(); s--; } } else if(c=='R') { if(!b.empty()) { a.push(b.top()); s++; S[s]=b.top()+S[s-1]; b.pop(); summax[s]=max(summax[s-1],S[s]); } } else if(c=='Q') { cin>>k; cout<<summax[k]<<endl; } } return 0; }

題目3:

直方圖是由在公共基線處對齊的一系列矩形組成的多邊形。
矩形具有相等的寬度,但可以具有不同的高度。
例如,圖例左側顯示了由高度為2,1,4,5,1,3,3的矩形組成的直方圖,矩形的寬度都為1:

在這裡插入圖片描述
通常,直方圖用於表示離散分佈,例如,文字中字元的頻率。
現在,請你計算在公共基線處對齊的直方圖中最大矩形的面積。
圖例右圖顯示了所描繪直方圖的最大對齊矩形。

輸入格式

輸入包含幾個測試用例。
每個測試用例佔據一行,用以描述一個直方圖,並以整數n開始,表示組成直方圖的矩形數目。
然後跟隨n個整數h1,…,hn。 這些數字以從左到右的順序表示直方圖的各個矩形的高度。 每個矩形的寬度為1。 同行數字用空格隔開。
當輸入用例為n=0時,結束輸入,且該用例不用考慮。**

輸出格式

對於每一個測試用例,輸出一個整數,代表指定直方圖中最大矩形的區域面積。
每個資料佔一行。
請注意,此矩形必須在公共基線處對齊

資料範圍

1≤n≤1e5, 0≤hi≤1e9

輸入樣例

7 2 1 4 5 1 3 3 4
1000 1000 1000 1000
0

輸出樣例

8
4000

思路(單調棧,時間複雜度O(n)):

單調棧的思想就是:及時排除不可能的選項,保持策略的高度有效性和秩序性。
本題中想要求最大的矩形區域面積,即需要列舉每個小矩形R並且找到該小矩形左側第一個比其矮的小矩形A,以及右側第一個比其矮的小矩形B,此時A前面的矩形對R來說已經無用了,對R後面即將要列舉的小矩形來說也沒有用,所以可以直接刪除,然後該序列就可以成為一個依照矩形高度單調遞增的棧。

程式碼:

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=100010;
ll res;//直方圖中最大矩形的區域面積
int h[N],hleft[N],hright[N],q[N],num;
//h[N]為直方圖的各個矩形的高度,hleft[N]儲存直方圖中各個矩形左邊第一個比該矩形矮的矩形編號
//hright[N]儲存直方圖中各個矩形右邊第一個比該矩形矮的矩形編號
//q[N]是單調棧,儲存單調遞增的矩形高度的矩形編號
void get(int n,int k[])//該函式查詢直方圖中各個矩形左邊第一個比該矩形矮的矩形編號
{
    for(int i=1;i<=n;i++)
    {
        while(h[i]<=h[q[num]]&&num) num--;//如果棧頂的矩形高度小於等於h[i]那麼前面棧中的元素均沒有用,所以出棧
        k[i]=q[num];//當前棧頂元素一定是第一個比該矩形矮的矩形
        q[++num]=i;//該矩形入棧
    }
}
int main()
{
    int n;
    while(cin>>n,n)//迴圈輸入n,當n為0時終止輸入
    {
        num=0;res=0;//num和res均得賦初值為0
        for(int i=1;i<=n;i++)
        cin>>h[i];
        h[0]=-1;
        h[n+1]=-1;//這裡讓h[0]和h[n+1]都為-1,是為了方便處理邊界問題
        get(n,hleft);
        reverse(h+1,h+n+1);//將[1,n+1)區間內的陣列翻轉即可把求右側的問題轉換為求左側的問題,只是會帶來後面計算矩形區域面積的麻煩...(編號直接繞暈)
        num=0;//這裡讓num=0相當於讓棧為空,不這麼做答案肯定不對
        get(n,hright);
        // for(int i=1;i<=n;i++)
        // cout<<hleft[i]<<" "<<n-hright[n-i+1]+1<<endl;
        for(int i=1;i<=n;i++)
        res=max(res,h[n-i+1]*(n-hright[n-i+1]+1-hleft[i]-1ll));//這裡的計算方式及編號自己去理解吧,畫畫就懂了
        cout<<res<<endl;
    }
    return 0;
}

題目4:

這裡有n列火車將要進站再出站,但是,每列火車只有1節,那就是車頭。這n列火車按1到n的順序從東方左轉進站,這個車站是南北方向的,它雖然無限長,只可惜是一個死衚衕,而且站臺只有一條股道,火車只能倒著從西方出去,而且每列火車必須進站,先進後出。
也就是說這個火車站其實就相當於一個棧,每次可以讓右側頭火車進棧,或者讓棧頂火車出站。
車站示意如圖:

        出站<——    <——進站
               |車|
               |站|
               |__|

現在請你按《字典序》輸出前20種可能的出棧方案。
輸入格式

輸入一個整數n,代表火車數量。

輸出格式

按照《字典序》輸出前20種答案,每行一種,不要空格。

資料範圍

1≤n≤20

輸入樣例

3

輸出樣例

123
132
213
231
321

思路:

本題方法很多,由於本題所給的資料範圍較小,所以猜測本題允許的時間複雜度應該是O(2ⁿ),所以可以考慮用搜索(列舉/遞迴)的方法去做,一共維護三個狀態,出站的序列用vector儲存,車站和進站序列用兩個棧儲存,對於每一步操作,要麼火車進站,要麼火車從車站出站。

程式碼:

#include<iostream>
#include<stack>
#include<vector>
using namespace std;
stack<int> a,b;//進站和車站的兩個棧
vector<int> c;//出站的vector序列
int cnt=20;//最多輸出20種方案
int n;
void dfs()//搜尋的函式
{
    if(!cnt) return;//如果超過20則返回
    if(c.size()==n)//如果出站序列元素個數達到n,則輸出
    {
        for(auto x:c)
        cout<<x;
        cout<<endl;
        cnt--;//輸出了一種方案,cnt--
        return;
    }
    if(!a.empty())//當a不為空,則選擇將a中棧頂元素出棧進入到序列c中
    {
        c.push_back(a.top());
        a.pop();
        dfs();//進入下一步
        a.push(c.back());
        c.pop_back();//兩步還原現場
    }
    if(!b.empty())//當b不為空,則選擇將b中棧頂元素出棧進入到棧a中
    {
        a.push(b.top());
        b.pop();
        dfs();//進入下一步
        b.push(a.top());
        a.pop();//兩步還原現場
    }
}
int main()
{
    cin>>n;
    for(int i=n;i>=1;i--)
    b.push(i);//先將要進站的序列存入棧b
    dfs();//開始搜尋
    return 0;
}

棧——未完待續