「狐狸」的 模板庫
@關於我,會寧狐狸,卑微蒟蒻想要留下些許痕跡
該blog最早寫於2020年是11月18日,距離我退役僅剩16天,很快我將參加最後一場NOIP,然後AFO,被機房遺忘。
我將在此blog中整理一些基礎模板,和基礎技巧,希望能對未來的學弟學妹有所幫助,作為我曾在這個機房拼搏過的些許痕跡。(點選</>可複製程式碼)
@常見實用操作
1 #include<bits/stdc++.h>//常見實用技巧 2 #define l long//定義l為long ,使下方l t等價於long t 3 #define int long long//定義int 為 long long 使得下文一切int 等價於long long,但要注意long long main() 錯誤,所以,下方必須寫為signed main() 4 using namespace std; 5 int n,m; 6 template<class T>//模板型別T,該程式碼僅修飾其下方的第一個函式或變數,作用為建立一個可適用任一型別的模板T 7 T sum(T a,T b){//當呼叫該函式時,T會自動適應為傳入引數的型別,如該程式中,T被自動指定為long long 8 return a+b;//當a,b型別不同時該函式會出錯,可以用sum<int>(n,m);強制指定T為long long 9 } 10 void Swap(int &a,int &b){//當寫作int a,int b時執行該函式,不會使傳入的m,n的值改變 11 l t=b;//但一旦使用了int &a(引用a,b修改a,b時就會修改傳入的引數,n,m) 12 b=a,a=t;//例:若定義int &x=n;那麼之後每一次對x修改,都會改變n的值 13 } 14 inline int read(){ //快讀,讀入速度顯著快於cin,scanf,但只能讀整數 15 int x=0,f=1;char ch=getchar();//x為讀入整數的絕對值,f為讀入數的符號 16 while(ch<'0'||ch>'9'){//讀取符號 17 if(ch=='-') f=-1;ch=getchar();} 18 while(ch>='0'&&ch<='9'){//讀取數 19 x=x*10+ch-'0';ch=getchar();} 20 return x*f;//返回數×符號 21 } 22 signed main()//signed本質上與int等價,但此刻int已被替換為long long ,所以需int處需全部寫為signed 23 { 24 n=read(),m=read(); 25 cout<<sum(n,m)<<endl; 26 Swap(n,m); 27 cout<<n<<" "<<m<<endl; 28 return 0; 29 }
@線段樹系列
壹--區間和查詢,區間加減乘修改:
1 #include<bits/stdc++.h>//線段樹,區間加減乘查詢 2 using namespace std; 3 int n,m,mod; 4 5 inline long long read() { 6 long long x = 0, f = 1;char ch = getchar(); 7 while (ch < '0' || ch > '9') {if (ch == '-')f = -1;ch = getchar();} 8 while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();} 9 return f * x; 10 } 11 12 13 struct tree 14 { 15 #define maxn 100010 16 #define int long long//將int巨集定義為了long long 17 #define lson rt*2//左,右兒子索引 18 #define rson rt*2+1 19 #define mid (s[rt].l+s[rt].r)/2 20 int p; 21 int arr[maxn]; 22 struct segment 23 { 24 segment() 25 {sum=0,add=0,mul=1;} 26 int sum,l,r,mul,add; 27 int size(){return r-l+1;} 28 }s[maxn<<2]; 29 void up(int rt) 30 {s[rt].sum=s[lson].sum+s[rson].sum;} 31 void down(int rt){//下傳懶標記,先乘後加,先總和後標記 32 s[lson].sum=(s[lson].sum*s[rt].mul+s[rt].add*s[lson].size())%p;//處理總和 33 s[rson].sum=(s[rson].sum*s[rt].mul+s[rt].add*s[rson].size())%p; 34 s[lson].mul=s[lson].mul*s[rt].mul%p;//處理標記 35 s[rson].mul=s[rson].mul*s[rt].mul%p; 36 s[lson].add=(s[lson].add*s[rt].mul+s[rt].add)%p; 37 s[rson].add=(s[rson].add*s[rt].mul+s[rt].add)%p; 38 s[rt].mul=1; 39 s[rt].add=0; 40 } 41 void init(int rt,int ll,int rr)//建樹,初始化 42 { 43 s[rt].l=ll,s[rt].r=rr; 44 if(ll==rr) 45 {s[rt].sum=arr[ll];return;} 46 init(lson,ll,mid); 47 init(rson,mid+1,rr); 48 up(rt); 49 } 50 void add(int rt,int ll,int rr,int k)//區間加,add為加法懶標記 51 { 52 if(s[rt].l>=ll&&s[rt].r<=rr) 53 { 54 s[rt].sum=(s[rt].sum+k*s[rt].size())%p; 55 s[rt].add=(s[rt].add+k)%p; 56 return ; 57 } 58 down(rt);//切記下傳 59 if(ll<=mid) 60 add(lson,ll,rr,k); 61 if(rr>mid) 62 add(rson,ll,rr,k); 63 up(rt);//切記上傳 64 } 65 void mul(int rt,int ll,int rr,int k)//區間乘,mul為乘法懶標記 66 { 67 if(s[rt].l>=ll&&s[rt].r<=rr) 68 { 69 s[rt].sum=(s[rt].sum*k)%p; 70 s[rt].add=s[rt].add*k%p; 71 s[rt].mul=s[rt].mul*k%p; 72 return ; 73 } 74 down(rt); 75 if(ll<=mid) 76 mul(lson,ll,rr,k); 77 if(rr>mid) 78 mul(rson,ll,rr,k); 79 up(rt); 80 } 81 int sum(int rt,int ll,int rr)//求區間和 82 { 83 int ans=0; 84 if(s[rt].l>=ll&&s[rt].r<=rr) 85 return s[rt].sum%p; 86 down(rt); 87 if(ll<=mid) 88 ans=(ans+sum(lson,ll,rr))%p; 89 if(rr>mid) 90 ans=(ans+sum(rson,ll,rr))%p; 91 return ans; 92 } 93 }tree; 94 signed main() 95 { 96 cin>>n>>m>>mod; 97 tree.p=mod; 98 for(int i=1;i<=n;i++) 99 cin>>tree.arr[i]; 100 tree.init(1,1,n);//記住建樹,否則段錯誤 101 while(m--){int opt=read();//讀取,呼叫 102 if(opt==1){int x=read(),y=read(),k=read();tree.mul(1,x,y,k);} 103 if(opt==2){int x=read(),y=read(),k=read();tree.add(1,x,y,k);} 104 if(opt==3){int x=read(),y=read();printf("%lld\n",tree.sum(1,x,y)%mod);}} 105 return 0; 106 }
線段樹知識略解
貳--區間最大值查詢,單點修改:
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long arr[100010]; 4 struct Tree{ 5 #define mid (s[rt].l+s[rt].r)/2 6 #define lson rt*2 7 #define rson rt*2+1 8 #define maxn 100010 9 #define inf 99999999 10 struct segment{ 11 long long max,l,r; 12 long long size(){return r+l-1;} 13 }s[maxn<<2]; 14 void init(long long rt,long long ll,long long rr){ 15 s[rt].l=ll,s[rt].r=rr; 16 if(ll==rr){ 17 s[rt].max=-inf;return ;} 18 init(lson,ll,mid); 19 init(rson,mid+1,rr); 20 s[rt].max=max(s[lson].max,s[rson].max); 21 } 22 long long query(long long rt,long long ll,long long rr){ 23 if(s[rt].l>=ll&&s[rt].r<=rr) 24 return s[rt].max; 25 long long ans=-inf; 26 if(ll<=mid)ans=max(ans,query(lson,ll,rr)); 27 if(rr>mid)ans=max(ans,query(rson,ll,rr)); 28 return ans; 29 } 30 void change(long long rt,long long ll,long long rr,long long x){ 31 if(s[rt].l>=ll&&s[rt].r<=rr){ 32 s[rt].max=x;return ;} 33 if(ll<=mid) change(lson,ll,rr,x); 34 if(rr>mid) change(rson,ll,rr,x); 35 s[rt].max=max(s[lson].max,s[rson].max); 36 } 37 }tree; 38 int n,m; 39 int main() 40 { 41 cin>>n>>m; 42 tree.init(1,1,n); 43 for(int i=1;i<=n;i++){ 44 int x;cin>>x;tree.change(1,i,i,x); 45 } 46 for(int i=1;i<=m;i++){ 47 int l,r;cin>>l>>r;cout<<tree.query(1,l,r)<<endl; 48 } 49 return 0; 50 }
@ST表,稀疏表
1 #include<bits/stdc++.h>//St表,建表O(logN)查詢O(1) 2 using namespace std; 3 int n,m; 4 const int K=30;//K看情況取值,要求K>log(n),空間允許時建議大於2log(n),但不可過大 5 int st[200010][K]; 6 inline int read() 7 { 8 int x=0,f=1;char ch=getchar(); 9 while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} 10 while (isdigit(ch)){x=x*10+ch-48;ch=getchar();} 11 return x*f; 12 } 13 void init() 14 { 15 for(int k=1;k<=25;k++){ 16 int d=pow(2,k-1); 17 for(int i=1;i<=n;i++){ 18 if(i+d<=n) st[i][k]=max(st[i][k-1],st[i+d][k-1]); 19 } 20 } 21 } 22 int query(int l,int r){ 23 int k=log2(r-l+1); 24 int x=r-pow(2,k)+1; 25 return max(st[l][k],st[x][k]); 26 } 27 int main() 28 { 29 cin>>n>>m; 30 for(int i=1;i<=n;i++) cin>>st[i][0]; 31 init(); 32 for(int i=1;i<=m;i++){ 33 int l,r;cin>>l>>r; 34 cout<<query(l,r)<<endl;} 35 return 0; 36 }