菜鸟ACM职业生涯模板总结
文章目录
- 基础算法
- 二分
- 高精度
- java大数
- 归并排序
- 第k小数
- 三分
- 数组模拟双向链表
- 快读
- 计算程序运行时间
- STL离散化
- 数学
- gcd
- 扩展欧几里得
- 容斥原理
- 卡特兰数
- 组合数
- 中国剩余定理
- 素数筛
- 逆元
- 质因数分解
- 数据结构
- ST表
- 优先队列
- 树状数组
- 单调栈
- 线段树
- 主席树
- 树上倍增求LCA
- 树链剖分
- 莫队
- 字符串
- 字典树
- 字符串hash
- 图论
- 图的连通子图
基础算法
二分
int bisearch(int l, int r,int x)
{while (l < r){int mid = l + r >> 1;if (check(mid)) r = mid;else l = mid + 1;}return l;
}
高精度
//加法
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;vector<int> add(vector<int> &A, vector<int> &B)
{vector<int> C;int t = 0; //进位for (int i = 0; i < A.size() || i < B.size(); i++){if (i < A.size())t += A[i];if (i < B.size())t += B[i];C.push_back(t % 10);t /= 10;}if (t)C.push_back(1);return C;
}
int main()
{string a, b;int t;cin >> t;for (int o = 1; o <= t; o++){vector<int> A, B;cin >> a >> b; //a="123456"for (int i = a.size() - 1; i >= 0; i--)A.push_back(a[i] - '0'); //A=[6,5,4,3,2,1]for (int i = b.size() - 1; i >= 0; i--)B.push_back(b[i] - '0');auto C = add(A, B); //c++11标准,for循环可以范围遍历;一个变量冒号一个list或容器。cout<<"Case "<<o<<":"<<endl;cout<<a<<" + "<<b<<" = ";for (int i = C.size() - 1; i >= 0; i--)printf("%d", C[i]); //个位数先放进去}cout<<endl;if(o!=t)cout<<endl;}
}
java大数
import java.util.Scanner;
import java.math.*;public class Main
{public static void main(String[] args) {Scanner cin = new Scanner(System.in);int t,i=1;t=cin.nextInt();while(i<=t){i++;BigInteger n,n1,k,bottom; n=cin.nextBigInteger();BigInteger s1=new BigInteger("1");//1BigInteger s2=new BigInteger("2");//2BigInteger mods=new BigInteger("1000000007");n1=n.add(s1);//n+1BigInteger sss;BigInteger s12=new BigInteger("12");//12BigInteger nd2;//(n+1)^2nd2=n1.pow(2);BigInteger nd21;//(n+1)^2-1nd21=nd2.subtract(s1);//k=nd2.multiply(nd21);k=k.divide(s12);bottom=n.multiply(n1);BigInteger bottom1,n2n1;bottom1=n.multiply(n1);n2n1=n.multiply(s2);n2n1=n2n1.add(s1);bottom1=bottom1.multiply(n2n1);bottom=bottom.multiply(bottom1);bottom=bottom.divide(s12);//System.out.println(bottom);BigInteger ans;ans=bottom;BigInteger s;s=n.multiply(n1);s=s.divide(s2);s=s.subtract(s1);BigInteger ans2,ks;ks=k.multiply(s);ans=ans.add(ks);System.out.println(ans.mod(mods));ans2=n.pow(2);ans2=ans2.multiply(bottom);System.out.println(ans2.mod(mods));}}
}
归并排序
void merge_sort(int start,int end){if(start>=end){return;}int start1=start,end1=(start+end)/2,start2=end1+1,end2=end;merge_sort(start1,end1);merge_sort(start2,end2);int k=start;while(start1<=end1&&start2<=end2){arr[k++]=a[start1]<a[start2]?a[start1++]:a[start2++];}while(start1<=end1){arr[k++]=a[start1++];}while(start2<=end2){arr[k++]=a[start2++];}for(int i=start;i<=end;i++){a[i]=arr[i];}
}
第k小数
#include <bits/stdc++.h>using namespace std;
#define ll long long
const int maxn = 5e6 + 10;inline int read()
{int 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 << 1) + (x << 3) + (ch ^ 48);ch = getchar();}return x * f;
}int q[maxn];
int quick_sort(int q[], int l, int r, int k)
{if (l >= r)return q[l];int i = l - 1, j = r + 1, x = q[l + r >> 1];while (i < j){doi++;while (q[i] < x);doj--;while (q[j] > x);if (i < j)swap(q[i], q[j]);}if (j - l + 1 >= k)return quick_sort(q, l, j, k);elsereturn quick_sort(q, j + 1, r, k - (j - l + 1));
}
int main()
{int n, k;int t;cin >> t;while (t--){//scanf("%d%d", &n, &k);n=read();k=read();for (int i = 0; i < n; i++)q[i]=read();cout << quick_sort(q, 0, n - 1, k) << endl;}
}
三分
int three_fen(int l,int r)
{while(l<r){int m1=(2*l+r)/3;int m2=(2*r+l+2)/3;if(calc(m1)<=calc(m2))r=m2-1;else{l=m1+1;}}return l;
}
数组模拟双向链表
#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int N=10000015,mod=1e9+7;
template<typename T>
void Debug(T x,string s){cout<<s<<": "<<x<<endl;
}
struct node
{int val,p_cnt;int next,last;
}a[N];#define PII pair<int,int>
// #define x first
// #define y second
#define PB push_back
int vis[N],vis_p[N];//value值在链表中的位置,value值对应的数组下标
struct linklist
{int head=1,tail=1,sz=0,mid=tail;void insertl(int tot){sz++;if(sz==1){head=tail=tot;vis_p[tot]=0;a[tot].last=-1;a[tot].next=-1;mid=tail;}else{a[tot].next=head;a[tot].last=-1;a[head].last=tot;vis_p[tot]=vis_p[head]-1;head=tot;if(sz%2==1){movel();}else{mid=mid;}}}void insertr(int tot){sz++;if(sz==1){head=tail=tot;vis_p[tot]=0;a[tot].last=-1;a[tot].next=-1;mid=tot;}else{a[tot].last=tail;a[tot].next=-1;a[tail].next=tot;vis_p[tot]=vis_p[tail]+1;tail=tot;if(sz%2==0){mover();}else mid=mid;}}void del(int tot){int tl=a[tot].last,tr=a[tot].next;if(tr!=-1)a[tl].next=tr;if(tl!=-1)a[tr].last=tl;if(tot==head){ head=a[head].next;}if(tot==tail){tail=a[tail].last;}if(vis_p[mid]>vis_p[tot]){if(sz%2==1) mover();else mid=mid;}else if(vis_p[mid]<vis_p[tot]){if(sz%2==0) movel();else mid=mid;}else if(mid==tot){if(sz%2==0) movel();else mover();}sz--;a[tot].last=a[tot].next=-1;}void movel(){mid=a[mid].last;}void mover(){mid=a[mid].next;}
}List;
int tot=0;
void solve()
{int posl=0,posr=0;a[0].last=a[0].next=-1;int q;scanf("%d ",&q);char c;for(int i=1;i<=q;i++){scanf("%c ",&c);// cout<<c<<endl;if(c=='L'){++tot;List.insertl(tot);}else if(c=='R'){++tot;List.insertr(tot);}else if(c=='G'){int x;scanf("%d ",&x);List.del(x);}else{printf("%d\n",List.mid);}}
}
int main()
{#ifndef ONLINE_JUDGEfreopen("b.txt", "r", stdin);freopen("bout.txt", "w", stdout);
#endif
// #ifndef ONLINE_JUDGE
// freopen("a.txt", "r", stdin);
// freopen("aout.txt", "w", stdout);
// #endifint t;t=1;while (t--)solve();
}
快读
template <typename _Tp>
inline _Tp read(_Tp &x) {char ch = getchar(), sgn = 0; x = 0;while (ch ^ '-' && !isdigit(ch)) ch = getchar();if (ch == '-') ch = getchar(), sgn = 1;while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar();if (sgn) x = -x;return x;
}
int main() {b = read(a);
}
//可读int, long long short
计算程序运行时间
cerr << "Time execute: " << clock() / (double)CLOCKS_PER_SEC << " sec" << endl;
STL离散化
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
数学
gcd
int gcd(int a,int b)
{return b?gcd(b,a%b):a;
}
扩展欧几里得
#include<iostream>
#include<cstdio>
#include<cmath>using namespace std;int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法
{if(b==0){x=1;y=0;return a; //到达递归边界开始向上一层返回}int r=exgcd(b,a%b,x,y);int temp=y; //把x y变成上一层的y=x-(a/b)*y;x=temp;return r; //得到a b的最大公因数
}
容斥原理
#include<bits/stdc++.h>using namespace std;
typedef long long ll;
const int Maxn = 20;
int Number[Maxn + 5];
ll N, M, Tot;
ll Ans = 0;
bool is_prime(int x)
{for(int i=2;i*i<=x;i++){if(x%i==0) return false;}return true;
}
ll Gcd(ll A, ll B){return !B ? A : Gcd(B, A % B);
}
void Dfs(ll Cur, ll Cnt, ll Limit, ll LCM){if (Cnt == Limit) {if (Limit & 1) {Ans += (N - 1) / LCM;}else {Ans -= (N - 1) / LCM;}return;}if (Cur >= Tot) {return ;}ll NowLCM = LCM == -1 ? Number[Cur] : LCM;Dfs(Cur + 1, Cnt + 1, Limit, Number[Cur] / Gcd(NowLCM, Number[Cur]) * NowLCM);Dfs(Cur + 1, Cnt, Limit, LCM);
}
int main()
{#ifndef ONLINE_JUDGEfreopen("a.txt","r",stdin);freopen("aout.txt","w",stdout);
#endifint tot=0;// Number[]=2;for(int i=2;i<=100;i++){if(is_prime(i)){Number[++tot]=i;}if(tot>17) break;}int t;cin>>t;while (t--) {cin>>N>>M;Tot = 1;Ans = 0;Tot=M+1;for (int i = 1; i < Tot; i++) {Dfs(1, 0, i, -1);} printf("%lld\n", N-Ans-1);}
}
卡特兰数
#include<cstdio>
#include<cstring>
#define N 60
using namespace std;
int main()
{int h[101][2*N+1],i,j,k,l,n;memset(h,0,sizeof(h));h[0][1]=1;h[1][1]=1;for(i=2;i<=100;i++){for(j=0;j<i;j++)for(k=1;k<N;k++)for(l=1;l<N;l++)h[i][k+l-1]+=h[j][k]*h[i-j-1][l];for(j=1;j<N;j++){h[i][j+1]+=h[i][j]/10;h[i][j]%=10;}}while(scanf("%d",&n)!=EOF){i=N;while(h[n][--i]==0);for(j=i;j>0;j--)printf("%d",h[n][j]);printf("\n");}return 0;
}
组合数
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const ll maxn=2*150007;
const ll mod=998244353;ll quick_mod(ll a, ll b)
{ll ans = 1;a %= mod;while(b){if(b & 1){ans = ans * a % mod;b--;}b >>= 1;a = a * a % mod;}return ans;
}ll C(ll n, ll m)
{if(m > n) return 0;ll ans = 1;for(int i=1; i<=m; i++){ll a = (n + i - m) % mod;ll b = i % mod;ans = ans * (a * quick_mod(b, mod-2) % mod) % mod;}return ans;
}ll Lucas(ll n, ll m)
{if(m == 0) return 1;return C(n % mod, m % mod) * Lucas(n / mod, m / mod) % mod;
}
//递推公式
const int N = 1e6 + 7, mod = 1e9 + 7;
int n, m, k, t;
int inv[N];
int fact[N], infact[N];void init (int n)
{fact[0] = infact[0] = inv[0] = inv[1] = 1;for (int i = 2; i <= n; ++ i) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;for (int i = 1; i <= n; ++ i) {fact[i] = 1ll * fact[i - 1] * i % mod;infact[i] = 1ll * infact[i - 1] * inv[i] % mod;}
}int C(int n, int m)
{if(n < m) return 0;if(m == 0 || n == m) return 1;return 1ll * fact[n] * infact[m] % mod * infact[n - m] % mod;
}
中国剩余定理
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;//扩展欧几里得,ax+by=gcd(a,b)
ll e_gcd(ll a,ll b,ll &x,ll &y){if(b==0){x=1,y=0;return a;}ll res=e_gcd(b,a%b,y,x);y-=(a/b)*x;return res;
}//中国剩余定理,pri[]存放互质的数,r[]存放余数,n为个数
ll china(ll pri[],ll r[],ll n){ll M=1,m,d,res=0;for(int i=0;i<n;i++) M*=pri[i]; //最小公倍数for(int i=0;i<n;i++){m=M/pri[i]; //m为除当前这个数不能整除以外都能够被其他数整除,就是其他数的最小公倍数ll x,y;d=e_gcd(pri[i],m,x,y); // pri[i]*x+m*y=gcd(pri[i],m]res=(res+y*m*r[i])%M; } return (res%M+M)%M; //满足的最小解
}ll pri[20],r[20];
int main(){int n;while(~scanf("%d",&n)){for(int i=0;i<n;i++)scanf("%lld %lld",&pri[i],&r[i]);ll ans=china(pri,r,n);printf("%lld\n",ans);}
}
素数筛
- 欧拉筛
#include<bits/stdc++.h>using namespace std;const int maxn=1e6;//这个是在哪一个范围内
int prime[maxn];
int visit[maxn];//1代表是偶数,0代表是奇数
void Prime()
{memset(visit,0,sizeof(visit));memset(prime,0,sizeof(visit));visit[1]=1;for (int i = 2;i <= maxn; i++) {if (!visit[i]) {prime[++prime[0]] = i; }for (int j = 1; j <=prime[0] && i*prime[j] <= maxn; j++) {visit[i*prime[j]] = 1;if (i % prime[j] == 0) {break;}}}
}
- 欧拉筛质因数个数
for(int i=2;i<=10000000;i++)
{if(!f[i])prm[++cnt]=i,num[i]=1;for(int j=1;j<=cnt && i*prm[j]<=10000000;j++){f[i*prm[j]]=true;num[i*prm[j]]=num[i]+1;if(i%prm[j]==0)break;}
}
- 欧拉函数
void euler()
{for (int i = 1; i <N; i++)a[i] = i;for (int i = 2; i <N; i += 2)a[i] /= 2;for (int i = 3; i <N; i += 2){if (a[i] == i)for (int j = i; j <N; j += i){if (j % i == 0)a[j] = a[j] - a[j] / i;}}a[0]=0;for(int i=1;i<N;i++){a[i]=a[i-1]+a[i];}
}
- 欧拉降幂
#include<iostream>
using namespace std;
typedef long long ll;
ll read(string s,ll mod){ll x=0;for(int i=0;i<s.length();i++)x=((x<<3)+(x<<1)+(s[i]^48))%mod;return (x+mod-1)%mod;
}
ll pow(ll s,ll n,ll mod){ll sum=1;while(n){if(n&1)sum=sum*s%mod;s=s*s%mod;n>>=1;}return sum;
}
ll phi(ll x){ll t=x;for(int i=2;i<=x/i;i++)if(x%i==0){while(x%i==0)x/=i;t=t*(i-1)/i;}if(x>1)t=t*(x-1)/x;return t;
}
int main(){ ll x,mod,n;string nn;cin>>x>>nn>>mod;if(x==0){if(nn=="1")cout<<1%mod;else cout<<"0";return 0;}x%=mod;n=read(nn,phi(mod));cout<<pow(x%mod,n,mod);
}
逆元
void init(){fac[0] = 1;for(int i=1;i<=MN;i++)fac[i] = (ll)fac[i-1]*i%mod;inv[MN] = qpow(fac[MN],mod-2);for(int i=MN-1;i>=0;i--)inv[i] = (ll)inv[i+1]*(i+1)%mod;
}int C(int n,int m){if(m>n) return 0;return (ll)fac[n]*inv[m]%mod*inv[n-m]%mod;
}ll pow_mod(ll a, ll b, ll p){//a的b次方求余pll ret = 1;while(b){if(b & 1) ret = (ret * a) % p;a = (a * a) % p;b >>= 1;}return ret;
}
ll Fermat(ll a, ll p){//费马求a关于b的逆元return pow_mod(a, p-2, p);
}
质因数分解
bool vis[N];
ll prime[N];
int cnt=0;
void primes()
{for(int i=2;i<=N;i++){if(vis[i]) {continue;}prime[++cnt]=i;for(int j=1;j<=N/i;j++){vis[i*j]=1;}}
}ll getprimefactor(long long n)
{ll ans=0;if(n==1){return 0;}if(!vis[N]){return 1;}for(int i=1;i<=cnt&&prime[i]*prime[i]<=n;i++){while(n%prime[i]==0){ans++;n/=prime[i];}}if(n>1){return ans+1;}return ans;
}
数据结构
ST表
void ST_init()
{for(int i=1;i<=N;++i)ST[i][0]=a[i];for(int j=1;j<30;++j){for(int i=1;i<=N;++i){if(i+(1<<j)-1>N) break;ST[i][j]=__gcd(ST[i][j-1],ST[i+(1<<(j-1))][j-1]);}}
}long long ST_query(int s,int e)
{int k=(int)((log(e-s+1.0)/log(2.0)));return __gcd(ST[s][k],ST[e-(1<<k)+1][k]);
}void ST_preowrk()
{for(int i=1;i<=n;i++) f[i][0]=a[i];int t=log(n)/log(2)+1;for(int j=1;j<t;j++){for(int i=1;i<=n-(1<<j)+1;i++){f[i][j]=max(f[i][j-1],f[i+1<<(j-1)][j-1]);}}
}ll ST_query(int l,int r)
{int k=log(r-l+1)/log(2);return max(f[l][k],f[r-(1<<k)+1][k]);
}
优先队列
#include <iostream>
#include <queue>
using namespace std;
int main()
{int n;while(cin>>n){int i,k,j,t1;long long sum=0;priority_queue<int,vector<int>,greater<int> > p;for(i=0;i<n;i++){cin>>k;p.push(k);}while(p.size()!=1){t1=p.top();p.pop();t1+=p.top();sum+=t1;p.pop();p.push(t1);}cout<<sum<<endl;}
}
树状数组
//树状数组模板
int sum[N];
int lowbit(int x)
{return x & (-x);
}
void add(int x, int num)
{while (x <= n){sum[x] += num;x += lowbit(x);}
}
int ask(int x)
{int res = 0;while (x > 0){res += sum[x];x -= lowbit(x);}return res;
}
单调栈
int tot=0;
h[m+1]=0;
for(int j=1;j<=m+1;j++){while(tot&&h[que[tot]]>h[j]){ans=max(ans,(j-1-que[tot-1])[que[tot]]);//这里可以理解为以 h[que[tot]]个高度可以向左向右拓展的面积。tot--;}que[++tot]=j;
}
线段树
- 单点修改,区间查询
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 100005;
const int INF = 0x3f3f3f3f;
int s[N << 2] ,lc[N << 2] ,rc[N << 2];
int n,m,num[N];
void build(int u ,int l ,int r) {lc[u] = l;rc[u] = r;if(l == r) {s[u] = num[l];return ;}int mid = (l + r) / 2;build(u * 2 , l , mid);build(u * 2 + 1 , mid + 1 ,r);s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
void change(int u , int x , int v) {if(lc[u] == x && rc[u] == x) {s[u] = v;return ;}int mid = (lc[u] + rc[u]) / 2;if(x <= mid)change(u * 2 , x , v);elsechange(u * 2 + 1 , x , v);s[u] = min(s[u * 2] , s[u * 2 + 1]);
}
int query(int u , int l ,int r) {int res = INF;if(l <= lc[u] && r >= rc[u]) {return s[u];}int mid = (lc[u] + rc[u]) / 2;if(l <= mid) res = min(res , query(u * 2 , l , r));if(r > mid) res = min(res , query(u * 2 + 1 , l , r));return res;
}
- 区间操作lowbit
#include<bits/stdc++.h>using namespace std;
typedef long long ll;
#define lowbit(x) ((x)&(-x))
const ll mod = 998244353;
ll powmod(ll a,ll b)
{ll res=1;a%=mod;while(b){if(b&1){res=res*a%mod;}a=a*a%mod;b>>=1;}return res;
}const int N = 1e5+50;
int n,m;
struct node
{int l,r;ll x,sum;int lazy;int flag;
}tree[N<<2];void push_up(int p)
{tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%mod;tree[p].flag=(tree[p<<1].flag&tree[p<<1|1].flag);
}void push_down(int p)
{if(tree[p].lazy==0) return;tree[p<<1].lazy+=tree[p].lazy;tree[p<<1|1].lazy+=tree[p].lazy;tree[p<<1].sum=(tree[p<<1].sum*powmod(2,tree[p].lazy))%mod;tree[p<<1|1].sum=(tree[p<<1|1].sum*powmod(2,tree[p].lazy))%mod;tree[p].lazy=0;
}void build_tree(int l,int r,int p)
{tree[p].l=l,tree[p].r=r;tree[p].lazy=tree[p].flag=0;if(l==r){scanf("%lld",&tree[p].x);tree[p].sum=tree[p].x;if(lowbit(tree[p].x)==tree[p].x) tree[p].flag=1;return;}int mid=l+r>>1;build_tree(l,mid,p<<1);build_tree(mid+1,r,p<<1|1);push_up(p);
}void update_tree(int l,int r,int p)
{if(l<=tree[p].l&&tree[p].r<=r&&tree[p].flag){tree[p].sum=(tree[p].sum*2)%mod;tree[p].lazy++;return;}if(tree[p].l==tree[p].r){tree[p].x=tree[p].sum=tree[p].sum+lowbit(tree[p].sum);if(lowbit(tree[p].x)==tree[p].x){tree[p].flag=1;}return;}push_down(p);int mid=(tree[p].l+tree[p].r)>>1;if(l<=mid) update_tree(l,r,p<<1);if(mid<r) update_tree(l,r,p<<1|1);push_up(p);
}ll ask_sum(int l,int r,int p)
{if(l<=tree[p].l&&tree[p].r<=r){return tree[p].sum;}ll res=0;push_down(p);int mid=(tree[p].l+tree[p].r)>>1;if(l<=mid) {res=(res+ask_sum(l,r,p<<1))%mod;}if(mid<r){res=(res+ask_sum(l,r,p<<1|1))%mod;}return res;
}void solve()
{scanf("%d",&n);build_tree(1,n,1);scanf("%d",&m);int op,l,r;for(int i=1;i<=m;i++){scanf("%d%d%d",&op,&l,&r);if(op==1){update_tree(l,r,1);}else{printf("%lld\n",ask_sum(l,r,1));}}
}int main()
{int t;scanf("%d",&t);while(t--){solve();}
}
- 区间修改,区间查询
#include<bits/stdc++.h>using namespace std;const int maxn=100010;int a[maxn+2];struct tree{int l,r;long long pre,add;
}t[4*maxn+2];void bulid(int p,int l,int r){t[p].l=l;t[p].r=r;if(l==r){t[p].pre=a[l];return;}int mid=l+r>>1;bulid(p*2,l,mid);bulid(p*2+1,mid+1,r);t[p].pre=t[p*2].pre+t[p*2+1].pre;
} void spread(int p){if(t[p].add){t[p*2].pre+=t[p].add*(t[p*2].r-t[p*2].l+1);t[p*2+1].pre+=t[p].add*(t[p*2+1].r-t[p*2+1].l+1);t[p*2].add+=t[p].add;t[p*2+1].add+=t[p].add;t[p].add=0;}
}void change(int p,int x,int y,int z){if(x<=t[p].l && y>=t[p].r){t[p].pre+=(long long)z*(t[p].r-t[p].l+1);t[p].add+=z;return;}spread(p);int mid=t[p].l+t[p].r>>1;if(x<=mid) change(p*2,x,y,z);if(y>mid) change(p*2+1,x,y,z);t[p].pre=t[p*2].pre+t[p*2+1].pre;
}long long ask(int p,int x,int y){if(x<=t[p].l && y>=t[p].r) return t[p].pre;spread(p);int mid=t[p].l+t[p].r>>1;long long ans=0;if(x<=mid) ans+=ask(p*2,x,y);if(y>mid) ans+=ask(p*2+1,x,y);return ans;
}int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);bulid(1,1,n);for(int i=1;i<=m;i++){int q,x,y,z;scanf("%d",&q);if(q==1){scanf("%d%d%d",&x,&y,&z);change(1,x,y,z);}else {scanf("%d%d",&x,&y);cout<<ask(1,x,y)<<endl;}}return 0;
}
//问最小值
//Q a b 询问(a,b)中最小值
//C a b 将a点值改为b
#include <bits/stdc++.h>
using namespace std;
#define maxn 200005int min(int a, int b)
{return a>b ? b : a;
}
int tree[4 * maxn];void pushup(int i)
{tree[i] = min(tree[i << 1], tree[i << 1 | 1]);
}void build(int i, int l, int r)
{if (l == r){scanf("%lld", &tree[i]);return;}int mid = (l + r) / 2;build(i << 1, l, mid);build(i << 1 | 1, mid + 1, r);pushup(i);
}void update(int i, int l, int r, int x, int val)
{if (l == r)///l==x??±???{tree[i] = val;return;}int mid = (l + r) / 2;if (x <= mid) update(i << 1, l, mid, x, val);else update(i << 1 | 1, mid + 1, r, x, val);pushup(i);
}int query(int i, int l, int r, int x, int y)
{if (x <= l && r <= y)return tree[i];int minn = 9999999;int mid = (l + r) / 2;if (x <= mid) minn = min(minn, query(i << 1, l, mid, x, y));if (y>mid) minn = min(minn, query(i << 1 | 1, mid + 1, r, x, y));return minn;
}int main()
{int n, m;int b, c;char a;while (scanf("%d%d", &n, &m) != -1){build(1, 1, n);while (m--){scanf(" %c%d%d", &a, &b, &c);if (a == 'Q')printf("%d\n", query(1, 1, n, b, c));elseupdate(1, 1, n, b, c);}}return 0;
}#include <bits/stdc++.h>
using namespace std;
#define maxn 200005
int tree[4 * maxn];void pushup(int i)
{tree[i] = max(tree[i << 1], tree[i << 1 | 1]);
}void build(int i, int l, int r)
{if (l == r){tree[i] = 0;return;}int mid = (l + r) / 2;build(i << 1, l, mid);build(i << 1 | 1, mid + 1, r);pushup(i);
}void update(int i, int l, int r, int x, int val)
{if (l == r){tree[i] = val;return;}int mid = (l + r) / 2;if (x <= mid) update(i << 1, l, mid, x, val);else update(i << 1 | 1, mid + 1, r, x, val);pushup(i);
}int query(int i, int l, int r, int x, int y)
{if (x <= l && r <= y)return tree[i];int maxm = 0;int mid = (l + r) / 2;if (x <= mid) maxm = max(maxm, query(i << 1, l, mid, x, y));if (y>mid) maxm = max(maxm, query(i << 1 | 1, mid + 1, r, x, y));return maxm;
}int main()
{int n, m;int b, c;char a;while (~scanf("%d%d", &n, &m)){build(1, 1, n);while (m--){scanf(" %c%d%d", &a, &b, &c);if (a == 'Q')printf("%d\n", query(1, 1, n, b, c));elseupdate(1, 1, n, b, c);}}
}
主席树
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e5; // 数据范围
int tot, n, m;
int sum[(maxn << 5) + 10], rt[maxn + 10], ls[(maxn << 5) + 10],rs[(maxn << 5) + 10];
int a[maxn + 10], ind[maxn + 10], len;
inline int getid(const int &val) { // 离散化return lower_bound(ind + 1, ind + len + 1, val) - ind;
}
int build(int l, int r) { // 建树int root = ++tot;if (l == r) return root;int mid = l + r >> 1;ls[root] = build(l, mid);rs[root] = build(mid + 1, r);return root; // 返回该子树的根节点
}
int update(int k, int l, int r, int root) { // 插入操作int dir = ++tot;ls[dir] = ls[root], rs[dir] = rs[root], sum[dir] = sum[root] + 1;if (l == r) return dir;int mid = l + r >> 1;if (k <= mid)ls[dir] = update(k, l, mid, ls[dir]);elsers[dir] = update(k, mid + 1, r, rs[dir]);return dir;
}
int query(int u, int v, int l, int r, int k) { // 查询操作int mid = l + r >> 1,x = sum[ls[v]] - sum[ls[u]]; // 通过区间减法得到左儿子的信息if (l == r) return l;if (k <= x) // 说明在左儿子中return query(ls[u], ls[v], l, mid, k);else // 说明在右儿子中return query(rs[u], rs[v], mid + 1, r, k - x);
}
inline void init() {scanf("%d%d", &n, &m);for (int i = 1; i <= n; ++i) scanf("%d", a + i);memcpy(ind, a, sizeof ind);sort(ind + 1, ind + n + 1);len = unique(ind + 1, ind + n + 1) - ind - 1;rt[0] = build(1, len);for (int i = 1; i <= n; ++i) rt[i] = update(getid(a[i]), 1, len, rt[i - 1]);
}
int l, r, k;
inline void work() {while (m--) {scanf("%d%d%d", &l, &r, &k);printf("%d\n", ind[query(rt[l - 1], rt[r], 1, len, k)]); // 回答询问}
}
int main() {init();work();return 0;
}
- 查询前k大和
#include <bits/stdc++.h>using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 7;
int root[MAXN],n,q,size,num;//size 内存池的大小
ll a[MAXN],s[MAXN],b[MAXN];struct HJT_tree{int l,r,cnt;//cnt记录出现次数 sum记录和 val记录节点的值ll sum,val;
}tree[MAXN*40];void build(int &now,int l,int r){now = ++size;tree[now].cnt = tree[now].sum = tree[now].val = 0;if(l == r) return ;int mid = (l+r)>>1;build(tree[now].l,l,mid);build(tree[now].r,mid+1,r);
}void modify(int &now,int pre,int l,int r,int p,int val){tree[now = ++size] = tree[pre];tree[now].cnt++,tree[now].sum += val;if(l == r){tree[now].val = val;return ;}int mid = (l+r)>>1;if(p <= mid) modify(tree[now].l,tree[pre].l,l,mid,p,val);else modify(tree[now].r,tree[pre].r,mid+1,r,p,val);
}
//查前k大值,因为节点存的是值 所以找大的 应该先往右边找 看右边(也就是大的)的数量符合情况嘛
ll query(int now,int pre,int l,int r,int k){if(l == r) return tree[now].val * k;//因为一个值可能出现多次 那么计算答案的时候要把他们都算上int mid = (l+r)>>1;int tmp = tree[tree[now].r].cnt - tree[tree[pre].r].cnt;if(tmp >= k) return query(tree[now].r,tree[pre].r,mid+1,r,k);else return query(tree[now].l,tree[pre].l,l,mid,k-tmp) + tree[tree[now].r].sum - tree[tree[pre].r].sum;//注意左边的k要变成k-tmp的形式
}int getid(ll x){ return lower_bound(b+1,b+1+num,x)-b; }int main(){int T;scanf("%d",&T);while(T--){memset(root,0,sizeof(root));size = 0;scanf("%d",&n);for(int i = 1;i <= n;i ++){scanf("%lld",&a[i]);b[i] = a[i];s[i] = s[i-1] + (1ll*i*i);//这里i会爆 所以开ll}/*****离散化 + 初始化****/sort(b+1,b+1+n);num = unique(b+1,b+1+n)-b-1;build(root[0],1,num);/***********************/for(int i = 1;i <= n;i ++){int p = getid(a[i]);modify(root[i],root[i-1],1,num,p,a[i]);}scanf("%d",&q);int l,r,k;while(q--){scanf("%d%d%d",&l,&r,&k);ll ans = query(root[r],root[l-1],1,num,k);ans += s[r-l+1];printf("%lld\n",ans);}}return 0;
}
树上倍增求LCA
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=1000010;
inline void read(int &n)
{char c=getchar();bool flag=0;n=0;while(c<'0'||c>'9') c=='-'?flag=1,c=getchar():c=getchar();while(c>='0'&&c<='9') n=n*10+c-48,c=getchar();flag==1?n=-n:n=n;
}
struct node
{int v,nxt;
}edge[MAXN];
int head[MAXN];
int num=1;
inline void add_edge(int x,int y)
{edge[num].v=y;edge[num].nxt=head[x];head[x]=num++;
}
int f[MAXN][21];
int deep[MAXN];
int n,m,root;
void dfs(int now)
{for(int i=head[now];i!=-1;i=edge[i].nxt)if(!deep[edge[i].v])deep[edge[i].v]=deep[now]+1,f[edge[i].v][0]=now,dfs(edge[i].v);
}
void PRE()
{for(int i=1;i<=19;i++) for(int j=1;j<=n;j++)f[j][i]=f[f[j][i-1]][i-1];
}
int LCA(int x,int y)
{if(deep[x]<deep[y]) swap(x,y);//x是靠下的那个。for(int i=19;i>=0;i--)if(deep[f[x][i]]>=deep[y])x=f[x][i];if(x==y) return x;for(int i=19;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];return f[x][0];
}
int main()
{memset(head,-1,sizeof(head));read(n);read(m);read(root);for(int i=1;i<=n-1;i++){int x,y;read(x);read(y);add_edge(x,y);add_edge(y,x);}deep[root]=1;dfs(root);PRE();for(int i=1;i<=m;i++){int x,y;read(x);read(y);printf("%d\n",LCA(x,y));}return 0;
}
树链剖分
void dfs1(int o) {son[o] = -1;siz[o] = 1;for (int j = h[o]; j; j = nxt[j])if (!dep[p[j]]) {dep[p[j]] = dep[o] + 1;fa[p[j]] = o;dfs1(p[j]);siz[o] += siz[p[j]];if (son[o] == -1 || siz[p[j]] > siz[son[o]]) son[o] = p[j];}
}
void dfs2(int o, int t) {top[o] = t;cnt++;dfn[o] = cnt;rnk[cnt] = o;if (son[o] == -1) return;dfs2(son[o], t); // 优先对重儿子进行 DFS,可以保证同一条重链上的点 DFS 序连续for (int j = h[o]; j; j = nxt[j])if (p[j] != son[o] && p[j] != fa[o]) dfs2(p[j], p[j]);
}
莫队
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;const int maxn = 100010;int n,m,blo;
int l=1,r=0;
int c[maxn],cnt[maxn],pos[maxn];
ll res=0;struct Q{int l,r,id;
}q[maxn];
struct Ans{ll a,b;
}ans[maxn];bool cmp(Q a,Q b){if(pos[a.l]==pos[b.l]) return a.r<b.r;return a.l<b.l;
}void add(int i){res-=1ll*cnt[c[i]]*cnt[c[i]];++cnt[c[i]];res+=1ll*cnt[c[i]]*cnt[c[i]];
}void del(int i){res-=1ll*cnt[c[i]]*cnt[c[i]];--cnt[c[i]];res+=1ll*cnt[c[i]]*cnt[c[i]];
}ll gcd(ll a,ll b){if(a<b) swap(a,b); return b==0?a:gcd(b,a%b);
}ll read(){ ll s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }int main(){n=read(),m=read();blo=sqrt(n);for(int i=1;i<=n;i++) c[i]=read(),pos[i]=(i-1)/blo+1;for(int i=1;i<=m;i++){q[i].l=read(),q[i].r=read();q[i].id=i;}sort(q+1,q+1+m,cmp); for(int i=1;i<=m;i++){while(l<q[i].l){ del(l); l++; }while(l>q[i].l){ add(l-1); l--; }while(r<q[i].r){ add(r+1); r++; }while(r>q[i].r){ del(r); r--; }if(q[i].l==q[i].r){ans[q[i].id]=(Ans){0,1};continue;}ans[q[i].id]=(Ans){res-(r-l+1),1ll*(r-l+1)*(r-l)};}for(int i=1;i<=m;i++){ll g=gcd(ans[i].a,ans[i].b);printf("%lld/%lld\n",ans[i].a/g,ans[i].b/g); }return 0;
}
字符串
字典树
#include <bits/stdc++.h>using namespace std;#define PII pair<int,int>
typedef long long ll;
const int maxn = 1e3 + 7;
const int N = 4e6 + 7;
char mp[maxn][maxn];
char str[maxn],t[maxn];
int n,m;
int trie[N][26],idx,val[N];void insert(char *s,int x)
{int p = 0,len = strlen(s);for(int i = 0;i < len;i ++){int ch = s[i] - 'a';if(!trie[p][ch]) trie[p][ch] = ++idx;p = trie[p][ch];}val[p] = x;
}int query(char *s)
{int p = 0,len = strlen(s);for(int i = 0;i < len;i ++){int ch = s[i] - 'a';p = trie[p][ch];if(!p) return -1;}if(val[p]) return val[p];else return -1;
}void init()
{for(int i = 0;i <= idx;i ++){memset(trie[i],0,sizeof(trie[i]));val[i] = 0;}idx = 0;
}int main()
{int tt;scanf("%d",&tt);while(tt--){init();scanf("%d%d",&n,&m);for(int i = 1;i <= n;i++){scanf("%s",mp[i]+1);}while(m--){int x;scanf("%s%d",str,&x);insert(str,x);}int flag = 0;ll sum = 0;for(int i = 1;i <= n;i++){for(int j = 1;j <= n;j++ ){int len = 0;if(mp[i][j] == '#') continue;while(mp[i][j] != '#' && j <= n){t[len++] = mp[i][j];j++;}t[len] = '\0';int ans = query(t);if(ans == -1) flag = 1;else sum += ans;}}for(int j=1;j<=n;j++){for(int i=1;i<=n;i++){int len = 0;if(mp[i][j] == '#') continue;while(mp[i][j] !='#'&& i <= n){t[len++] = mp[i][j];i++;}t[len] = '\0';int ans = query(t);if(ans == -1) flag = 1;else sum += ans;}} if(flag) printf("-1\n");else printf("%lld\n",sum); }
}
字符串hash
#include<iostream>
#include<algorithm>using namespace std;typedef unsigned long long ULL;
const int N=1e6+10,M=131;int n,m;
char str[N];ULL p[N],h[N];
ULL get(int l,int r)
{return h[r]-h[l-1]*p[r-l+1];
}int main()
{cin>>n>>m;cin>>str+1;p[0]=1;for(int i=1;i<=n;i++){h[i]=h[i-1]*M+str[i];p[i]=p[i-1]*M;}while(m--){int l1,r1,l2,r2;cin>>l1>>r1>>l2>>r2;if(get(l1,r1)==get(l2,r2)) puts("Yes");elseputs("No");}return 0;
}
图论
图的连通子图
#include<bits/stdc++.h>
const int N=1005;
using namespace std;
vector<int> t[N];
int vis[N]={0};
void dfs(int k)
{for(int i=0;i<t[k].size();i++){if(vis[t[k][i]]==0){ vis[t[k][i]]=1;dfs(t[k][i]);}}
}
int main()
{int n,m;//n个顶点,m条边 cin>>n>>m;int a,b;//边所连接的两个顶点for(int i=1;i<=m;i++){cin>>a>>b;t[a].push_back(b);t[b].push_back(a);}int ans=0;//记录连通块数量 for(int i=1;i<=n;i++){if(vis[i]==0){vis[i]=1;dfs(i);ans++; } }cout<<ans<<endl;return 0;
}#include <bits/stdc++.h>using namespace std;
const int maxn = 3e5 + 3;
int edge[maxn][maxn];
vector<int> t[maxn];
int pre[maxn], root[maxn];void init(int nn)
{for (int i = 1; i <= nn; i++)pre[i] = i;
}
int find(int x)
{int f = x;while (x != pre[x]) //找到x的父节点x = pre[x];int j;while (f != pre[f]) //依次将x上面的节点的父节点赋为x;{j = f;f = pre[f];pre[j] = x;}return x;
}void merge(int a, int b)
{int t1, t2;t1 = find(a);t2 = find(b);if (t1 != t2){pre[t2] = t1;}
}int block(int nn)
{int ans = 0;for (int i = 1; i <= nn; i++)root[pre[i]] = 1;for (int i = 1; i <= nn; i++)ans += root[i];return ans;
}int main()
{int n, m;cin >> n >> m;init(n);for (int i = 1; i <= m; i++){int a,b;scanf("%d%d",&a,&b);t[a].push_back(b);t[b].push_back(a);// merge(a, b);}for (int i = 1; i <= n; i++){vector<int>::iterator it;for(it=t[i].begin();it!=t[i].size())printf("%d",block(n));}
}// void init(int nn)
// {// for(int i=1;i<=nn;i++)
// pre[i]=i;
// }
// int find(int x)
// {// int f=x;
// while(x!=pre[x])//找到x的父节点
// x=pre[x];// int j;
// while(f!=pre[f])//依次将x上面的节点的父节点赋为x;
// {// j=f;
// f= pre[f];
// pre[j]=x;
// }
// return x;
// }// void merge(int a,int b)
// {// int t1,t2;
// t1=find(a);
// t2=find(b);
// if(t1!=t2)
// {// pre[t2]=t1;
// }
// }// int block(int nn)
// {// int ans=0;
// for(int i=1;i<=nn;i++)
// root[pre[i]]=1;
// for(int i=1;i<=nn;i++)
// ans+=root[i];
// return ans;
// }
// int main()
// {// scanf("%d%d",&n,&m);
// int a,b;//边所连接的两个顶点
// init(n);
// for(int i=1;i<=m;i++)
// {// scanf("%d%d",&a,&b);
// t[a].push_back(b);
// t[b].push_back(a);
// merge(a,b);
// }
// printf("%d",block(n));
// return 0;
// }
菜鸟ACM职业生涯模板总结相关推荐
- ACM Latex模板subsubsection换行
ACM Latex模板subsubsection默认是不会换行的, 如果使用\\系统会报错. 其实可以用\ 来换行, 注意后面有一个空格. \subsubsection{section title}\ ...
- ACM数学模板1 高斯消元 Gaussian Elimination
声明: 题目来源: https://www.luogu.com.cn/problem/P3389 https://www.luogu.com.cn/problem/P2447 https://ac.n ...
- acm算法模板(1)
1. 几何 4 1.1 注意 4 1.2 几何公式 4 1.3 多边形 6 1.4 多边形切割 9 1.5 浮点函数 10 1.6 面积 15 1.7 球面 16 1.8 三角形 17 1.9 三维几 ...
- ACM常用模板-数据结构
数据结构方面常用模板总结,大多数代码摘自网络,个人整理总结 string: 任意进制转换:itoa(int n,char* s,int r) //将10进制n转换为r进制并赋给s流:#include& ...
- ACM算法模板总结(分类详细版)
本文模均引用于y总的算法模板,网址:AcWing (转载请注明出处,本文属于持续更新ing.......biubiubiu......) 本人码风比起y总真的差远了,所以敲一遍后,还是想把y总的搬上来 ...
- Nobleman__ ACM 比赛模板 (C++ Java)个人总结 (不断更新) (自用)
声明 : 本人刚学算法一年,都是自己做题常用的模板,不时总结下. 大致分为:乱七八糟, 数论,图论,动态规划,几何,Java 还有一些奇葩定理, 常用素数: 1 e 8 左 右 : 91815541 ...
- ACM职业生涯回忆录学习方法感悟
2018年的5月,我在西安邀请赛打铁,陕西省赛三等奖.2019年的5月,还是在西工大,邀请赛拿金,圆满退役.(不过省赛才第十不是很满意呜呜呜) 2018年年底区域赛赛季结束的时候,我被问到明年区域赛是 ...
- 【菜鸟源码模板】最新素材下载类网站 带会员充值系统 HTML5自适应手机版
介绍: 一款非常大气的站长素材下载类网站源码,带会员系统,带充值系统. 1.该模板由站长亲自制作,代码干净整洁; 2.效果相当的炫酷,相当简洁大气高端,模板简单,全部已数据调用,只需后台修改栏目名称即 ...
- acm - 动态规划模板
动态规划 思维导图: 数字三角形模型 每次只能向下走或者向右走.从起点走到终点. 题目给定一个 n × n n \times n n×n 的矩阵,矩阵中的每个格子上有一个价值为 w w w 的物品.给 ...
最新文章
- eclipse中中文字体过小
- 百雀羚、林清轩、逐本走红背后,植物基护肤品的春天来了?
- git放弃本地修改,强制覆盖本地文件
- 面试时被问到「有没有职业规划时」,要怎么回答?
- 一个USB HUB电路分享
- cbrt c语音_C语言有哪些鲜为人知的特性?
- List<?> list= new ArrayList<?>接口引用指向实现类的对象.
- Oracle 12.2 新特性 | PDB不同字符集变更深入解析
- 快递实名制正式实施 市民最担心个人信息泄露
- 使用SoapUI测试Web Service
- Redis 经典 必问21问,BAT面试都会问,你会回答吗?
- 解决Mac安装Adobe软件错误代码501问题(PS AI AE PR)mac安装Adobe软件报错501解决方案
- 依行科技日常实习面经
- zMUD里的颜色触发
- 使用torchvision.models
- TinyG 入门06
- 8句极易踩中买家雷点的口头禅,你中了哪几条?
- xheditor使用
- 啃光学论文的笔记(1)
- 和Leo一起做爱线段树的好孩子HDU5238 Calculator
热门文章
- 【孙伟】基础实用Photoshop设计软件标准视频教程-孙伟-专题视频课程
- HADOOP实战——蔬菜价格统计(win10伪分布式环境)
- 杭州电子科技大学信息工程学院,计算机本科生考研情况很弱?
- 使用SSD训练自己的模型(从图片标注开始)
- 超级Windows快捷键大全
- 教你选择巫师之怒里最适合自己的职业
- linux写入二进制文件内容,fopen , fread fwrite 函数读写二进制文件 问题总结
- python脚本如何自动升级?
- 开源大师章文嵩打造低碳淘宝 称技术人才创新很重要
- apex英雄机器人探路者怎么玩_Apex英雄探路者怎么玩 探路者人物操作技巧分享