主頁 > 後端開發 > 堆疊與佇列(含單調堆疊與單調佇列)

堆疊與佇列(含單調堆疊與單調佇列)

2021-06-20 06:13:31 後端開發

堆疊

演算法思路

堆疊(\(stack\))又名堆疊,它是一種運算受限的線性表,限定僅在表尾進行插入和洗掉操作的線性表,這一端被稱為堆疊頂,相對地,把另一端稱為堆疊底,向一個堆疊插入新元素又稱作進堆疊、入堆疊或壓堆疊,它是把新元素放到堆疊頂元素的上面,使之成為新的堆疊頂元素;從一個堆疊洗掉元素又稱作出堆疊或退堆疊,它是把堆疊頂元素洗掉掉,使其相鄰的元素成為新的堆疊頂元素, ----摘自 百度百科

附圖

由上述資料可知,堆疊是一個“先進后出”的資料結構,是只能在堆疊頂插入和洗掉的資料結構,如圖,支持進堆疊(\(push\))和出堆疊(\(pop\))兩種操作,由于只能從一端進堆疊,一端出堆疊,所以任一元素,如上圖中的\(s_2\),必須得在比它后進堆疊的\(s_3\sim s_n\)\(s_n\)\(s_{top}\))都出堆疊以后才能出堆疊,換句話說,先進來的元素必須等后進來的元素都出堆疊后才能出堆疊,故堆疊被稱為“先進后出(\(FILO\))表”,

代碼片段

進堆疊

進堆疊很簡單,只需要將堆疊頂上移一格,然后在新的一格中放入元素即可,

void push(int x){
  s[++top]=x;
}

出堆疊

出堆疊也很簡單,只需要將堆疊頂下移一格即可,且不需要替換,因為如果有元素進堆疊需占用此格時會將它替換,

void pop(){
  top--;
}

例題

P1739 運算式括號匹配

大意

給定一個以\(@\)結尾的運算式,判斷其括號(只有“(”和“)”)是否匹配,
“(()())”,“((()))”匹配,但是“())”,“)()(”不匹配,

思路

如果只判斷左右括號的數量的話顯然是不行的,因為有很多資料顯然過不去,如“)()(”,“())(()”等,
所以,這時候,我們就要使用堆疊了,逐個讀入運算式,若為“(”則入堆疊(顯然此時堆疊應該為\(char\)型別),若為“)”則判斷,若堆疊頂為慷訓為“)”,即不為“(”,說明此時這個右半圓括號沒有匹配到左半圓括號,說明不匹配,另外,若最后堆疊頂不為\(0\),說明還有剩下的括號沒被匹配,也是不合法的,

代碼
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char a[260],s[260];
int top=0;
int main(){
	cin>>a;
	for(int i=0;i<strlen(a);i++){
		if(a[i]=='('){
			s[++top]=a[i];
		}else if(a[i]==')'){
			if(a[i]==')'&&s[top]=='('){
				top--;
			}else{
				cout<<"NO";
				return 0;
			}
		}
	}
	if(top==0){
		cout<<"YES";
	}else{
		cout<<"NO";
	}
	return 0;
}

P1449 后綴運算式求值

科普

逆波蘭式(\(Reverse Polish notation\)\(RPN\),或逆波蘭記法),也叫后綴運算式(將運算子寫在運算元之后),
一個運算式\(E\)的后綴形式可以如下定義:
(1)如果\(E\)是一個變數或常量,則E的后綴式是\(E\)本身,
(2)如果\(E\)\(E1 op E2\)形式的運算式,這里\(op\)是任何二元運算子,則E的后綴式為\(E1'E2' op\),這里\(E1'\)\(E2'\)分別為\(E1\)\(E2\)的后綴式,
(3)如果\(E\)\((E1)\)形式的運算式,則\(E1\)的后綴式就是\(E\)的后綴式,
如:我們平時寫\(a+b\),這是中綴運算式,寫成后綴運算式就是:\(ab+\)
\((a+b)*c-(a+b)/e\)的后綴運算式為:
\((a+b)*c-(a+b)/e\)
\(((a+b)*c)((a+b)/e)-\)
\(((a+b)c*)((a+b)e/)-\)
\((ab+c*)(ab+e/)-\)
\(ab+c*ab+e/-\)

這里用樹解釋上述樣例:
首先我們構建上述運算式的樹,使得樹的中序遍歷為運算式(因為我們寫的是中綴運算式,若想將前綴運算式,即波蘭式 變為樹,則需構建樹讓其前序遍歷為運算式即可),那么,這棵樹的后序遍歷就是逆波蘭式,

大意

給出后綴運算式,輸出其值,

思路

一個個讀入后綴運算式,遇到數字進堆疊,遇到符號計算堆疊頂和堆疊頂后一位的元素,最后輸出堆疊頂即可,

代碼
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s[260],top=1;
char x;
int main(){
	while(x!='@'){
		x=getchar();
		if(x=='.'){
			top++;
		}else{
			if(x>='0'&&x<='9'){
				s[top]=s[top]*10+(x-'0');
			}
			if(x=='+'){
				top--;
				s[top-1]+=s[top];
				s[top]=0;
			}else if(x=='-'){
				top--;
				s[top-1]-=s[top];
				s[top]=0;
			}else if(x=='*'){
				top--;
				s[top-1]*=s[top];
				s[top]=0;
			}else if(x=='/'){
				top--;
				s[top-1]/=s[top];
				s[top]=0;
			}else if(x=='@'){
				break;
			}
		}
	}
	cout<<s[--top];
	return 0;
}

佇列

演算法思路

堆疊是一端進和出的資料結構,對應地,佇列是一端進、另一端出的資料結構,

佇列是一種特殊的線性表,特殊之處在于它只允許在表的前端(front)進行洗掉操作,而在表的后端(rear)進行插入操作,和堆疊一樣,佇列是一種操作受限制的線性表,進行插入操作的端稱為隊尾,進行洗掉操作的端稱為隊頭, ——摘自 百度百科


與堆疊類似,不多贅述,

單調堆疊

演算法思路

顧名思義,單調堆疊是一種堆疊內元素具有單調性的堆疊,也就是說,我們將數列內的元素入堆疊,且要讓堆疊內元素單調遞增或單調遞減,維護這樣一個堆疊也很簡單(以下假設維護單調遞增的單調堆疊),我們將堆疊內的元素\(s_i\)表示為數列\(a\)中的元素的下標,也就是說,當你在看到堆疊內有一個元素\(x\)時,它表示的不是數字\(x\),而是表示\(a\)陣列中的元素\(a_x\),這一點需要特別注意,入堆疊時,如果堆疊頂元素表示的值大于加入的值(即\(a_{s_{top}}>a_x\)\(x\)表示加入的元素,顯然為\(a\)陣列中的元素下標),那么將\(top--\),即把堆疊頂踢出去,因為加進來的\(x\),即代表的\(a_x\),已經小于堆疊頂了,而我們要維護單調遞增的堆疊,所以若\(x\)直接加入會破壞單調性,故要讓堆疊頂出堆疊,等到所有的要踢出堆疊頂\(top\)都被踢出后(即現在的堆疊頂\(top\)符合\(a_{s_{top}}<a_x\)),就可以將\(x\)入堆疊了,
那么,單調堆疊有什么作用呢?顯然,你可以維護一個單調遞增的堆疊,通過按順序一個個入堆疊序列中的元素,可以求出長度為\(n\)的序列\(a\)中的前\(k\)個元素的最小值(\(0<k\le n\)),因為堆疊是單調遞增的,所以按順序加入前\(k\)個元素后,堆疊頂一定是前\(k\)個數中的最小值,但是,你顯然可以不用單調堆疊來解決這一個非常基礎的問題,單調堆疊的主要作用之一就是求出序列中每個數右(或左)邊第一個比它大(或者小)的數(詳情請見例題1),

例題

P5788 【模板】單調堆疊 & P2947 [USACO09MAR]Look Up S

大意

求出序列中每個數右邊第一個比它大的數,

思路

維護一個單調遞減的堆疊,那么,對于每一個元素,讓它被踢出去的那個元素一定是第一個比它大的元素,(建議自己畫圖好好分析一下),

代碼
#include<iostream>
#include<cstdio>
#define maxn 100005
using namespace std;
int n,a[maxn];
int s[maxn],top=0;
int ans[maxn];
void push(int x){
	while(a[s[top]]<a[x]&&top>0){
		ans[s[top]]=x;
		top--;
	}
	s[++top]=x;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	s[++top]=1;
	for(int i=2;i<=n;i++){
		push(i);
	}
	for(int i=1;i<=n;i++){
		printf("%d ",ans[i]);
	}
	return 0;
}

P1901 發射站

大意

\(n\)個發射站,每一個發射站有一個高度\(h_i\)和能量值\(v_i\),對于每個發射站\(i\),它左邊和右邊第一個比它高的發射站都可以接收到它發出的信號(即累計值加上\(v_i\)),求每個信號塔累計的能量值總和的最大值,

思路

同上兩題,只不過要加兩次,

代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000005
using namespace std;
int n,a[maxn],v[maxn];
int s[maxn],top=0;
int ans[maxn];
void push(int x){
	while(a[s[top]]<a[x]&&top>0){
		ans[x]+=v[s[top]];
		top--;
	}
	s[++top]=x;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i],&v[i]);
	}
	s[++top]=1;
	for(int i=2;i<=n;i++){
		push(i);
	}
	memset(s,0,sizeof(s));
	top=0;
	s[++top]=n;
	for(int i=n-1;i>=1;i--){
		push(i);
	}
	int mmax=-1;
	for(int i=1;i<=n;i++){
		mmax=max(mmax,ans[i]);
	}
	printf("%d ",mmax);
	return 0;
}

P2422 良好的感覺

大意

有一長為\(n\)的序列\(a\),定義某區間\([l,r]\)的值\(comfort_{l,r} = \min\limits_{i=l}^{r}{a_i} \times \sum\limits_{i=l}^{r}{a_i}\),求\(max(comfort_{i,j})(0 < i\le j\le n)\)

思路

可以想象,列舉每個區間需要耗費大量的時間,這很可能會使我們\(TLE\),我們不妨列舉\(min(i,j)\),顯然我們只需要列舉\(n\)次,因為我們可以從\(1\)\(n\)列舉\(i\),計算以\(a_i\)為最小值的區間中的最大\(comfort_{l,r}\),因為\(a_i \ge 1\),所以我們只要讓區間越大越好,所以我們需要列舉的區間即為從\(a_i\)開始,左右兩邊各延伸到離它最近的比它小的兩個位置(不包括這兩個比它小的值)(因為這樣就可以保證區間內沒有小于\(a_i\)的數,即\(a_i\)為區間內最小值,且區間最大),計算所有的\(a_i\)計算的區間的和乘\(a_i\)(即以\(a_i\)為最小值的最大\(comfort\)值)的最大值即為所求最大值,

代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100005
using namespace std;
int n,a[maxn];
long long pre[maxn];
int le[maxn],ri[maxn];
int s[maxn],top=0;
void pushr(int x){
	while(a[s[top]]>a[x]&&top>=0){
		ri[s[top]]=x;
		top--;
	}
	s[++top]=x;
}
void pushl(int x){
	while(a[s[top]]>a[x]&&top>=0){
		le[s[top]]=x;
		top--;
	}
	s[++top]=x;
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		pre[i]=pre[i-1]+a[i];
	}
	s[++top]=1;
	for(int i=2;i<=n;i++){
		pushr(i);
	}
	memset(s,0,sizeof(s));
	top=0;
	s[++top]=n;
	for(int i=n-1;i>=1;i--){
		pushl(i);
	}
	for(int i=1;i<=n;i++){
		ri[i]=ri[i]==0?n+1:ri[i];
	}
	long long ans=-1;
	for(int i=1;i<=n;i++){
		ans=max(ans,(long long)(a[i]*(pre[ri[i]-1]-pre[le[i]])));
	}
	printf("%lld",ans);
	return 0;
}

單調佇列

演算法思路

我們剛才講到,單調堆疊可以算出一組資料中前\(k\)個資料中的最值(雖然不用單調堆疊更簡單易懂),那么,如何計算一組資料中任意連續\(k\)個資料的最值呢(\(0<k\le n\))?這時,我們就要用到單調佇列了(注:用線段樹也可以),
單調佇列相當于單調堆疊,但是它在隊頭也可以進行洗掉操作(即\(head++\)),以上述題目(即例題\(1\))為例,我們只要控制這個單調佇列的隊頭始終滿足在所求范圍內即可,更詳細的思路見例題\(1\)

例題

P1886 滑動視窗 /【模板】單調佇列

大意

有一串長\(n\)的序列,有一個長\(m\)的視窗從\(1\)\(n-m+1\)滑動(\(0<m<=n\)),求每滑動一次視窗的最值,

思路

模板題,
維護佇列\(q\)(當然能用\(STL\)),(這里講最大值的做法,最小值同理)每次加入一個元素,從隊尾把小于此元素的從隊尾出隊(因為當前的元素已經比它大了,且視窗向右滑動,所以它必定不可能再一次成為最大值),從隊首將不在范圍內的元素從隊首出隊,這時隊首即為最大值,
代碼中,先將前\(k-1\)個元素入隊,然后回圈\(i\)\(k\le i\le n\)),列舉隊尾,用\(push\)函式從隊尾插入,同時從隊頭刪去\(i-k+1\)之前的元素,即已經不在滑動視窗內的元素,輸出隊頭,

代碼
#include<iostream>
#include<cstdio>
#define maxn 1000005
using namespace std;
int n,k;
int a[maxn];
int q1[maxn],q2[maxn],h1=1,t1=0,h2=1,t2=0;//q1維護最大值,q2維護最小值 
int ans1[maxn],ans2[maxn];
void push1(int x,int l){
	while(t1>=h1&&a[x]>a[q1[t1]]){
		t1--;
	}
	q1[++t1]=x;
	while(t1>=h1&&q1[h1]<l){
		h1++;
	}
}
void push2(int x,int l){
	while(t2>=h2&&a[x]<a[q2[t2]]){
		t2--;
	}
	q2[++t2]=x;
	while(t2>=h2&&q2[h2]<l){
		h2++;
	}
}
int main(){
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	q1[++t1]=1;
	q2[++t2]=1;
	for(int i=2;i<=k;i++){
		push1(i,-1);
		push2(i,-1);
	}
	ans1[1]=q1[h1];
	ans2[1]=q2[h2];
	for(int i=k+1;i<=n;i++){
		push1(i,i-k+1);
		push2(i,i-k+1);
		ans1[i-k+1]=q1[h1];
		ans2[i-k+1]=q2[h2];
	}
	for(int i=1;i<=n-k+1;i++){
		printf("%d ",a[ans2[i]]);
	}
	printf("\n");
	for(int i=1;i<=n-k+1;i++){
		printf("%d ",a[ans1[i]]);
	}
	return 0;
}

雙倍經驗(只需求最大值):P2032 掃描

P2629 好訊息,壞訊息

大意

給定一個環,問從任意元素開始累加,有多少種情況使得累加時總和\(tot\)恒大于等于\(0\)

思路

斷環成鏈,維護單調佇列和前綴和\(pre_i\),若某一長度為\(n\)的序列\(i\sim i+n-1\)的最小值減\(pre_{i-1}\)大于零的話即可行,

代碼
#include<iostream>
#include<cstdio>
#define maxn 1000005
using namespace std;
int n,k;
int a[maxn*2],pre[maxn*2];
int q[maxn],h=1,t=0;
int ans[maxn];
void push(int x,int l){
	while(t>=h&&pre[x]<pre[q[t]]){
		t--;
	}
	q[++t]=x;
	while(t>=h&&q[h]<l){
		h++;
	}
}
int main(){
	scanf("%d",&n);
	k=n;
	n*=2;
	for(int i=1;i<=k;i++){
		scanf("%d",&a[i]);
		a[i+k]=a[i];
	}
	for(int i=1;i<=n;i++){
		pre[i]=pre[i-1]+a[i];
	}
	q[++t]=1;
	for(int i=2;i<=k;i++){
		push(i,-1);
	}
	ans[1]=q[h];
	for(int i=k+1;i<n;i++){
		push(i,i-k+1);
		ans[i-k+1]=q[h];
	}
	int tot=0;
	for(int i=1;i<=n-k;i++){
		if(pre[ans[i]]-pre[i-1]>=0){
			tot++;
		}
	}
	printf("%d",tot);
	return 0;
}

單調佇列優化DP

例題

P1725 琪露諾

大意

有一串長度為\(n+1\)的序列\(a\),從\(0\)出發,在某個節點\(i\)能走到\(i+l\sim i+r\)的任意位置,\(tot\)累加當前位置的\(a_i\),求離開時的最大\(tot\)值(\(i+r>n\)代表從\(i\)節點能離開),

思路

顯然此題暴力代碼復雜度為\(O(N^2)\)\(f_i=\max\limits_{j=max(0,i-r)}^{i-l}{f_j}(l<=i<=n)\),那么,我們只要開一個單調佇列求前文的\(max(f_j)\)即可,

代碼

(細節很多)

#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1000005
#define INF 0x3f
using namespace std;
int n,l,r;
int a[maxn];
int q[maxn],h=1,t=0,maxx[maxn];
int f[maxn];
void push(int x,int l){
	while(f[x]>f[q[t]]&&h<=t){
		t--;
	}
	while(q[h]<l&&h<=t){
		h++;
	}
	q[++t]=x;
}
void clear(int l){
	while(q[h]<l&&h<=t){
		h++;
	}
}
int main(){
	scanf("%d%d%d",&n,&l,&r);
	memset(f,0x80,sizeof(f));
	memset(q,-1,sizeof(q));
	for(int i=0;i<=n;i++){
		scanf("%d",&a[i]);
	}
	f[0]=0;
	push(0,-1);
	for(int i=l;i<=n;i++){
		if(i-l>=l){
			push(i-l,max(0,i-r));
		}else{
			clear(max(0,i-r));
		}
		if(q[h]==-1){
			f[i]=f[maxn-1]+a[i];
		}else{
			f[i]=f[q[h]]+a[i];
		}
//		for(int j=i-l;j>=max(0,i-r);j--){
//			f[i]=max(f[i],f[j]+a[i]);
//		}
	}
	int ans=-INF;
	for(int i=n;i>=n-r+1;i--){
		ans=max(ans,f[i]);
	}
	printf("%d",ans);
	return 0;
}

P2627 Mowing the Lawn G

大意

有一個長度為\(n\)的序列,選出若干個元素,使得選出的元素沒有連續超過\(k\)個的(\(0<k<=n\)),求選出元素的和的最大值,

思路

選出的數的和的最大值可以轉換成刪去的數的和的最小值,

代碼
#include<iostream>
#include<cstdio>
#define maxn 100005
using namespace std;
long long n,k,a[maxn],f[maxn];
long long q[maxn],h=0,t=0;
long long tot=0;
void push(long long x,long long l){
	while(f[x]<f[q[t]]&&h<=t){
		t--;
	}
	while(q[h]<l&&h<=t){
		h++;
	}
	q[++t]=x;
}
int main(){
	scanf("%lld%lld",&n,&k);
	for(long long i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		tot+=a[i];
	}
	for(int i=1;i<=n;i++){
		f[i]=f[q[h]]+a[i];
		push(i,i-k);
	}
	long long mmin=f[n-k];
	for(long long i=n-k+1;i<=n;i++){
		mmin=min(f[i],mmin);
	}
	printf("%lld",tot-mmin);
	return 0;
}
/*
5 4
1 2 3 4 5
*/

雙倍經驗:P2034 掃描

qzez1926 玉米實驗

大意

給定一個\(n*n\)的矩陣\(a\),有\(t\)次詢問,每次詢問以\((x_i,y_i)\)為左上角、長寬均為\(k\)的矩陣中,最大值與最小值的差值是多少,

思路

首先,我們還是顯然能得出暴力的代碼:
\(ans_i = \max\limits_{x=x_i , y=y_i}^{x_i+k-1 , y_i+k-1}{a_{{x},{y}}} - \min\limits_{x=x_i , y=y_i}^{x_i+k-1 , y_i+k-1}{a_{{x},{y}}}\)
然后,由于\(k\)是給定的,這讓我們想到可以用單調佇列優化\(max(a_{{x},{y}})\)\(min(a_{{x},{y}})\),即預處理矩陣\(a\),算出矩陣每一行的長\(k\)的滑動視窗中的最值,詢問時直接查詢子矩陣第一列的最值即可,

代碼
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 1005
#define INF 99999999
using namespace std;
int n,k,t,x,y;
int a1[maxn][maxn],a2[maxn][maxn];
int q1[maxn],q2[maxn],h1=1,t1=0,h2=1,t2=0;
int ans1[maxn][maxn],ans2[maxn][maxn];
void push1(int i,int x,int l){//找最小值 
	while(a1[i][x]<a1[i][q1[t1]]&&h1<=t1){
		t1--;
	}
	q1[++t1]=x;
	while(q1[h1]<l&&h1<=t1){
		h1++;
	}
}
void push2(int i,int x,int l){//找最大值 
	while(a2[i][x]>a2[i][q2[t2]]&&h2<=t2){
		t2--;
	}
	q2[++t2]=x;
	while(q2[h2]<l&&h2<=t2){
		h2++;
	}
}
void doit(int i){
	memset(q1,0,sizeof(q1));
	memset(q2,0,sizeof(q2));
	h1=1;t1=0;h2=1;t2=0;
	q1[++t1]=1;q2[++t2]=1;
	for(int j=2;j<k;j++){
		push1(i,j,-1);
		push2(i,j,-1);
	}
	for(int j=k;j<=n+k;j++){
		push1(i,j,j-k+1);
		push2(i,j,j-k+1);
		ans1[i][j-k+1]=q1[h1];
		ans2[i][j-k+1]=q2[h2];
	}
}
int main(){
	memset(a1,0x3f,sizeof(a1));
	scanf("%d%d%d",&n,&k,&t);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			scanf("%d",&a1[i][j]);
			a2[i][j]=a1[i][j];
		}
	}
	for(int i=1;i<=n;i++){
		doit(i);
	}
//	printf("\n");
//	for(int i=1;i<=n;i++){
//		for(int j=1;j<=n;j++){
//			printf("%d ",a2[i][ans2[i][j]]);
//		}
//		printf("\n");
//	}
//	printf("\n");
	while(t--){
		scanf("%d%d",&x,&y);
		int mmax=-1,mmin=INF;
		for(int i=0;i<k;i++){
			mmax=max(mmax,a2[x+i][ans2[x+i][y]]);
			mmin=min(mmin,a1[x+i][ans1[x+i][y]]);
		}
		printf("%d\n",mmax-mmin);
	}
	return 0;
} 
/*
5 3 2
5 1 2 6 3
1 3 5 2 7
7 2 4 6 1
9 9 8 6 5
0 6 9 3 9
2 1
1 2
*/

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/288133.html

標籤:其他

上一篇:python通過字典實作購物車案例-用戶端

下一篇:Dubbo 3.0.0 正式發布,王者歸來!

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more