快读/快写
| 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; |
| } |
| inline void print(int x) { |
| if(x<0){putchar('-');x=-x;} |
| if(x/10)print(x/10); |
| putchar(x%10+'0'); |
| } |
st表查找max和min(可查位置)
| struct ST { |
| int n,mx[M][22],mn[M][22],a[M]; |
| void init() { |
| for(int i=1;i<=n;i++)mx[i][0]=mn[i][0]=i; |
| for(int j=1;j<20;j++) |
| for(int i=1;i+(1<<j)-1<=n;i++) { |
| mx[i][j]=a[mx[i][j-1]] > a[mx[i+(1<<(j-1))][j-1]] ? mx[i][j-1] : mx[i+(1<<(j-1))][j-1]; |
| mn[i][j]=a[mn[i][j-1]] < a[mn[i+(1<<(j-1))][j-1]] ? mn[i][j-1] : mn[i+(1<<(j-1))][j-1]; |
| } |
| } |
| int get_max(int l,int r) { |
| int k=log2(r-l+1); |
| return a[mx[l][k]] > a[mx[r-(1<<k)+1][k]] ? a[mx[l][k]] : a[mx[r-(1<<k)+1][k]]; |
| } |
| int get_min(int l,int r) { |
| int k=log2(r-l+1); |
| return a[mn[l][k]] < a[mn[r-(1<<k)+1][k]] ? a[mn[l][k]] : a[mn[r-(1<<k)+1][k]]; |
| } |
| int get_max_pos(int l,int r) { |
| int k=log2(r-l+1); |
| return a[mx[l][k]] > a[mx[r-(1<<k)+1][k]] ? mx[l][k] : mx[r-(1<<k)+1][k]; |
| } |
| int get_min_pos(int l,int r) { |
| int k=log2(r-l+1); |
| return a[mn[l][k]] < a[mn[r-(1<<k)+1][k]] ? mn[l][k] : mn[r-(1<<k)+1][k]; |
| } |
| }st; |
树状数组(单点和区间)
| struct BIT { |
| int n,c[M],c1[M],c2[M]; |
| void init() { |
| for(int i=0;i<=n+2;i++)c[i]=c1[i]=c2[i]=0; |
| } |
| int lowbit(int x) {return x&-x;} |
| |
| |
| void add(int x,int v) { |
| for(int i=x;i<=n;i+=lowbit(i)) |
| c[i]+=v; |
| } |
| int sum(int x) { |
| int ans=0; |
| for(int i=x;i>0;i-=lowbit(i)) |
| ans+=c[i]; |
| return ans; |
| } |
| int query(int l,int r) { |
| return sum(r)-sum(l-1); |
| } |
| |
| |
| void ADD(int x,int v) { |
| for(int i=x;i<=n;i+=lowbit(i)) |
| c1[i]+=v ,c2[i]+=v*x; |
| } |
| void range_add(int l,int r,int v) { |
| ADD(l,v);ADD(r+1,-v); |
| } |
| int QUERY(int x) { |
| int ans=0; |
| for(int i=x;i;i-=lowbit(i)) |
| ans+=(x+1)*c1[i]-c2[i]; |
| return ans; |
| } |
| int range_query(int l,int r) { |
| return QUERY(r)-QUERY(l-1); |
| } |
| }tr; |
tarjan(缩点)
| struct Suo_Point { |
| int h1[M],h2[M],ne[M<<1],e[M<<1],tot; |
| void add(int h[],int from,int to) { |
| e[++tot]=to; ne[tot]=h[from]; h[from]=tot; |
| } |
| |
| int dfn[M],low[M],cnt; |
| int id[M],num[M],scnt; |
| bool vis[M]; |
| stack<int>st; |
| void tarjan(int now) { |
| dfn[now]=low[now]=++cnt; |
| st.push(now); |
| vis[now]=1; |
| for(int i=h1[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(dfn[to]==0) { |
| tarjan(to); |
| low[now]=min(low[now],low[to]); |
| } |
| else if(vis[to])low[now]=min(low[now],dfn[to]); |
| } |
| if(dfn[now]==low[now]) { |
| scnt++; |
| while(1) { |
| int k=st.top(); |
| st.pop(); |
| vis[k]=0; |
| id[k]=scnt; |
| num[scnt]++; |
| if(k==now)break; |
| } |
| } |
| } |
| |
| int n,m,in[M]; |
| void solve() { |
| for(int i=1;i<=n;i++) |
| if(dfn[i]==0)tarjan(i); |
| |
| for(int i=1;i<=n;i++) |
| for(int j=h1[i];j;j=ne[j]) { |
| int to=e[j]; |
| if(id[i]!=id[to]) { |
| add(h2,id[i],id[to]); |
| in[id[i]]++; |
| } |
| } |
| } |
| }graph; |
割点
| struct Cut_point { |
| int h[M],ne[M],e[M],tot=1; |
| void add(int from,int to) { |
| e[++tot]=to; ne[tot]=h[from]; h[from]=tot; |
| } |
| |
| int n,m; |
| int dfn[M],low[M],cnt; |
| bool vis[M]; |
| void tarjan(int now,int fa) { |
| dfn[now]=low[now]=++cnt; |
| int x=0; |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(dfn[to]==0) { |
| tarjan(to,fa); |
| low[now]=min(low[now],low[to]); |
| if(now==fa)x++; |
| if(now!=fa&&low[to]>=dfn[now])vis[now]=1; |
| } |
| low[now]=min(low[now],dfn[to]); |
| } |
| if(x>=2&&now==fa)vis[fa]=1; |
| } |
| void init() { |
| for(int i=1;i<=n;i++) |
| if(dfn[i]==0)tarjan(i,i); |
| } |
| |
| }graph; |
树链剖分
| struct ShuLian { |
| int h[M],ne[M<<1],e[M<<1],tot; |
| void add(int from,int to) { |
| e[++tot]=to; ne[tot]=h[from]; h[from]=tot; |
| } |
| |
| int dep[M],f[M],son[M],siz[M]; |
| void dfs1(int now,int fa) { |
| dep[now]=dep[fa]+1; |
| siz[now]=1; |
| f[now]=fa; |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(to==fa)continue; |
| dfs1(to,now); |
| siz[now]+=siz[to]; |
| if(siz[to]>siz[son[now]])son[now]=to; |
| } |
| } |
| |
| int dfn[M],idx[M],top[M],id; |
| void dfs2(int now,int fa) { |
| dfn[now]=++id; |
| idx[id]=now; |
| top[now]=fa; |
| if(son[now]==0)return ; |
| dfs2(son[now],fa); |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(dfn[to]==0)dfs2(to,to); |
| } |
| } |
| |
| #define ul (u<<1) |
| #define ur (u<<1|1) |
| struct Tree { |
| int l,r,len; |
| int sum,la; |
| }tr[M<<2]; |
| int n,a[M]; |
| |
| void pu(int u) { |
| tr[u].sum=(tr[ul].sum+tr[ur].sum); |
| |
| } |
| |
| void pd(int u) { |
| if(tr[u].la==0)return ; |
| |
| tr[ul].sum=(tr[ul].sum+tr[u].la*tr[ul].len); |
| tr[ur].sum=(tr[ur].sum+tr[u].la*tr[ur].len); |
| tr[ul].la=(tr[ul].la+tr[u].la); |
| tr[ur].la=(tr[ur].la+tr[u].la); |
| |
| |
| tr[u].la=0; |
| } |
| |
| void build(int u,int l,int r) { |
| tr[u]={l,r,r-l+1,0,0}; |
| if(l==r) { |
| tr[u].sum=a[idx[l]]; |
| |
| return ; |
| } |
| int mid=(l+r)>>1; |
| build(ul,l,mid); |
| build(ur,mid+1,r); |
| pu(u); |
| } |
| |
| void up(int u,int l,int r,int v) { |
| if(tr[u].l>r||tr[u].r<l)return ; |
| if(tr[u].l>=l&&tr[u].r<=r) { |
| tr[u].sum=(tr[u].sum+tr[u].len*v); |
| tr[u].la=(tr[u].la+v); |
| |
| return ; |
| } |
| pd(u); |
| up(ul,l,r,v); |
| up(ur,l,r,v); |
| pu(u); |
| } |
| |
| int query(int u,int l,int r) { |
| if(tr[u].l>r||tr[u].r<l)return 0ll; |
| if(tr[u].l>=l&&tr[u].r<=r)return tr[u].sum; |
| pd(u); |
| return (query(ul,l,r)+query(ur,l,r)); |
| |
| } |
| |
| void change(int x,int y,int v) { |
| while(top[x]!=top[y]) { |
| if(dep[top[x]]<dep[top[y]])swap(x,y); |
| up(1,dfn[top[x]],dfn[x],v); |
| x=f[top[x]]; |
| } |
| if(dfn[x]>dfn[y])swap(x,y); |
| up(1,dfn[x],dfn[y],v); |
| } |
| |
| |
| int ask(int x,int y) { |
| int res=0; |
| while(top[x]!=top[y]) { |
| if(dep[top[x]]<dep[top[y]])swap(x,y); |
| res+=query(1,dfn[top[x]],dfn[x]); |
| |
| x=f[top[x]]; |
| } |
| if(dfn[x]>dfn[y])swap(x,y); |
| res+=query(1,dfn[x],dfn[y]); |
| |
| return res; |
| } |
| |
| void UP(int x,int y) { |
| up(1,dfn[x],dfn[x]+siz[x]-1,y); |
| } |
| |
| int QUERY(int x) { |
| return query(1,dfn[x],dfn[x]+siz[x]-1); |
| } |
| |
| void init(int rot=1) { |
| dfs1(rot,0); |
| dfs2(rot,0); |
| build(1,1,n); |
| } |
| |
| }Tr; |
lCA(树剖)
| struct LCA_ShuLian { |
| int h[M],ne[M<<1],e[M<<1],tot; |
| void add(int from,int to) { |
| e[++tot]=to; ne[tot]=h[from]; h[from]=tot; |
| } |
| int siz[M],f[M],son[M],dep[M]; |
| void dfs1(int now,int fa) { |
| f[now]=fa; |
| siz[now]=1; |
| dep[now]=dep[fa]+1; |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(to==fa)continue; |
| dfs1(to,now); |
| siz[now]+=siz[to]; |
| if(siz[to]>siz[son[now]])son[now]=to; |
| } |
| } |
| int top[M]; |
| void dfs2(int now,int rot) { |
| top[now]=rot; |
| if(son[now])dfs2(son[now],rot); |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(to==f[now]||to==son[now])continue; |
| dfs2(to,to); |
| } |
| } |
| int lca(int x,int y) { |
| |
| while(top[x]!=top[y]) { |
| if(dep[top[x]]<dep[top[y]])swap(x,y); |
| x=f[top[x]]; |
| } |
| return dep[x]<dep[y]?x:y; |
| } |
| int dis(int x,int y) { |
| return dep[x]+dep[y]-2*dep[lca(x,y)]; |
| } |
| }tr; |
LCA(倍增)
| struct LCA_st { |
| int h[M],ne[M<<1],e[M<<1],tot; |
| int Base=20; |
| void add(int from,int to) { |
| e[++tot]=to; ne[tot]=h[from]; h[from]=tot; |
| } |
| int dep[M],f[M][22]; |
| void dfs(int now,int fa) { |
| f[now][0]=fa; |
| dep[now]=dep[fa]+1; |
| for(int i=1;i<=Base;i++) |
| f[now][i]=f[f[now][i-1]][i-1]; |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(to==fa)continue; |
| dfs(to,now); |
| } |
| } |
| int lca(int x,int y) { |
| if(dep[x]<dep[y])swap(x,y); |
| for(int i=Base;i>=0;i--) |
| if(dep[x]-(1<<i)>=dep[y])x=f[x][i]; |
| if(x==y)return x; |
| for(int i=Base;i>=0;i--) |
| if(f[x][i]!=f[y][i]) |
| x=f[x][i],y=f[y][i]; |
| return f[x][0]; |
| } |
| int dis(int x,int y) { |
| return dep[x]+dep[y]-2*dep[lca(x,y)]; |
| } |
| }tr; |
二进制gcd
| inline int gcd(int a, int b) { |
| int az=__builtin_ctz(a),bz=__builtin_ctz(b),z=az>bz?bz:az,diff; |
| b>>=bz; |
| while(a) { |
| a>>=az; |
| diff=b-a; |
| az=__builtin_ctz(diff); |
| if(a<b)b=a; |
| a=diff<0?-diff:diff; |
| } |
| return b<<z; |
| } |
dinic
| struct Max_flow { |
| int h[N],ne[M<<1],e[M<<1],w[M<<1],tot=1; |
| void add(int from,int to,int wi) { |
| e[++tot]=to; w[tot]=wi; ne[tot]=h[from]; h[from]=tot; |
| e[++tot]=from;w[tot]=0; ne[tot]=h[to]; h[to]=tot; |
| } |
| int S=N-2,T=N-1; |
| int cur[N],dep[N]; |
| bool bfs() { |
| memcpy(cur,h,sizeof(h)); |
| memset(dep,0,sizeof(dep)); |
| queue<int>q; |
| q.push(S); |
| dep[S]=1; |
| while(!q.empty()) { |
| int now=q.front(); |
| q.pop(); |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(dep[to]==0&&w[i]>0) |
| dep[to]=dep[now]+1,q.push(to); |
| } |
| } |
| return dep[T]; |
| } |
| int dfs(int now,int sum) { |
| if(now==T)return sum; |
| int ans=0; |
| for(int i=cur[now];i&∑i=ne[i]) { |
| cur[now]=i; |
| int to=e[i]; |
| if(dep[to]==dep[now]+1&&w[i]>0) { |
| int k=dfs(to,min(sum,w[i])); |
| if(k==0)dep[to]=0; |
| w[i]-=k; |
| w[i^1]+=k; |
| sum-=k; |
| ans+=k; |
| } |
| } |
| return ans; |
| } |
| int dinic() { |
| int ans=0; |
| while(bfs())ans+=dfs(S,inf); |
| return ans; |
| } |
| }flow; |
费用流(最小费用EK)
| struct Cost_flow { |
| int h[N],ne[M],e[M],w[M],c[M],tot=1; |
| void add(int from,int to,int wi,int ci) { |
| e[++tot]=to; w[tot]=wi; c[tot]=ci; ne[tot]=h[from]; h[from]=tot; |
| e[++tot]=from;w[tot]=0; c[tot]=-ci; ne[tot]=h[to]; h[to]=tot; |
| } |
| int S=N-2,T=N-1; |
| bool st[N]; |
| int dis[N],flow[N],pre[N]; |
| bool spfa() { |
| memset(dis,0x3f,sizeof(dis)); |
| memset(flow,0,sizeof(flow)); |
| queue<int>q;q.push(S); |
| flow[S]=inf;dis[S]=0;st[S]=1; |
| while(!q.empty()) { |
| int now=q.front(); |
| q.pop();st[now]=0; |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(w[i]>0&&dis[to]>dis[now]+c[i]) { |
| dis[to]=dis[now]+c[i]; |
| pre[to]=i; |
| flow[to]=min(flow[now],w[i]); |
| if(st[to]==0)st[to]=1,q.push(to); |
| } |
| } |
| } |
| return flow[T]; |
| } |
| int EK() { |
| int sum=0,ans=0; |
| while(spfa()) { |
| int tmp=flow[T]; |
| ans+=tmp*dis[T]; |
| sum+=tmp; |
| for(int i=T;i!=S;i=e[pre[i]^1]) { |
| w[pre[i]]-=tmp; |
| w[pre[i]^1]+=tmp; |
| } |
| } |
| cout<<sum<<' '<<ans<<endl; |
| return ans; |
| } |
| }flow; |
| |
KMP算法模板(可以不止字符串匹配)
| struct KMP { |
| char s[M]; |
| int ne[M],n; |
| void init() { |
| for(int i=2,j=0;i<=n;i++) { |
| while(j&&s[i]!=s[j+1])j=ne[j]; |
| if(s[i]==s[j+1])j++; |
| ne[i]=j; |
| } |
| } |
| void find(char *t) { |
| int m=strlen(t+1); |
| for(int i=1,j=0;i<=m;i++) { |
| while(j&&t[i]!=s[j+1])j=ne[j]; |
| if(t[i]==s[j+1])j++; |
| if(j==n) { |
| cout<<i-n+1<<'\n'; |
| j=ne[j]; |
| } |
| } |
| } |
| }kmp; |
Manacher
| struct Manacher { |
| char s[M<<1],t[M]; |
| int p[M],n=1,m; |
| void init() { |
| m=strlen(t+1); |
| s[0]='@';s[1]='#'; |
| for(int i=1;i<=m;i++) |
| s[++n]=t[i],s[++n]='#'; |
| for(int i=1,mid=0,r=0;i<=n;i++) { |
| if(i<=r)p[i]=min(p[2*mid-i],r-i+1); |
| while(s[i-p[i]]==s[i+p[i]])p[i]++; |
| if(p[i]+i>r)mid=i,r=i+p[i]-1; |
| } |
| } |
| }Ma; |
| |
PAM(回文树)
| struct PAM { |
| char s[M]; |
| int len[M],fail[M],num[M],ch[M][26],tot=1,n; |
| int get_fail(int x,int i) { |
| while(i-len[x]-1<=0||s[i-len[x]-1]!=s[i])x=fail[x]; |
| return x; |
| } |
| void init() { |
| fail[0]=1;len[1]=-1; |
| n=strlen(s+1); |
| int p=0; |
| for(int i=1;i<=n;i++) { |
| int fa=get_fail(p,i); |
| if(!ch[fa][s[i]-'a']) { |
| fail[++tot]=ch[get_fail(fail[fa],i)][s[i]-'a']; |
| ch[fa][s[i]-'a']=tot; |
| len[tot]=len[fa]+2; |
| } |
| p=ch[fa][s[i]-'a']; |
| num[p]++; |
| } |
| } |
| void get_num() { |
| for(int i=tot;i>=2;i--) |
| num[fail[i]]+=num[i]; |
| } |
| }pam; |
二分图匹配
| struct Max_match { |
| int vis[M],match[M],t[M]; |
| int n,m; |
| void init(int nn,int mm) { |
| n=nn,m=mm; |
| for(int i=0;i<=max(n,m);i++) |
| vis[i]=t[i]=match[i]=-1; |
| } |
| bool dfs(int now,int num) { |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(vis[to]==num)continue; |
| vis[to]=num; |
| if(match[to]==-1||dfs(match[to],num)) { |
| match[to]=now; |
| return 1; |
| } |
| } |
| return 0; |
| } |
| int find() { |
| int ans=0; |
| for(int i=1;i<=n;i++) |
| if(dfs(i,i))ans++; |
| return ans; |
| } |
| }Match; |
| |
后缀数组
| struct Suffix_Array { |
| char s[M]; |
| int sa[M],rk[M],height[M]; |
| int cnt[M],id[M],k1[M],pre[M<<1]; |
| int n,m; |
| |
| bool cmp(int l1,int l2,int len) { |
| return pre[l1]==pre[l2]&&pre[l1+len]==pre[l2+len]; |
| } |
| |
| void init() { |
| n=strlen(s+1),m=150; |
| |
| for(int i=1;i<=m;i++)cnt[i]=0; |
| for(int i=1;i<=n;i++)cnt[rk[i]=s[i]]++; |
| for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1]; |
| for(int i=n;i>=1;i--)sa[cnt[rk[i]]--]=i; |
| |
| for(int len=1;;len<<=1) { |
| int k=0; |
| for(int i=n;i>n-len;i--)id[++k]=i; |
| |
| for(int i=1;i<=n;i++) |
| if(sa[i]>len)id[++k]=sa[i]-len; |
| |
| for(int i=1;i<=m;i++)cnt[i]=0; |
| for(int i=1;i<=n;i++)cnt[k1[i]=rk[id[i]]]++; |
| for(int i=1;i<=m;i++)cnt[i]+=cnt[i-1]; |
| for(int i=n;i>=1;i--)sa[cnt[k1[i]]--]=id[i]; |
| |
| for(int i=0;i<=n;i++)pre[i]=rk[i]; |
| int p=0; |
| for(int i=1;i<=n;i++)rk[sa[i]]=cmp(sa[i-1],sa[i],len)?p:++p; |
| if(p==n)break; |
| m=p; |
| } |
| |
| for(int i=1,k=0;i<=n;i++) { |
| if(k)k--; |
| while(s[i+k]==s[sa[rk[i]-1]+k])k++; |
| height[rk[i]]=k; |
| } |
| } |
| }SA; |
SAM
| struct Suffix_Auto { |
| char s[M]; |
| int np=1,tot=1,n; |
| int ch[M<<1][26],fa[M<<1],len[M<<1],siz[M<<1],d[M]; |
| void insert(int c,int id) { |
| int p=np;np=++tot; |
| len[np]=len[p]+1;siz[np]=1;d[id]=tot; |
| for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np; |
| if(!p)fa[np]=1; |
| else { |
| int q=ch[p][c]; |
| if(len[p]+1==len[q])fa[np]=q; |
| else { |
| int nq=++tot;len[nq]=len[p]+1; |
| memcpy(ch[nq],ch[q],sizeof(ch[q])); |
| fa[nq]=fa[q];fa[q]=fa[np]=nq; |
| for(;p&&ch[p][c]==q;p=fa[p])ch[p][c]=nq; |
| } |
| } |
| } |
| |
| int a[M<<1],b[M<<1]; |
| void Sort() { |
| for(int i=1;i<=tot;i++)a[len[i]]++; |
| for(int i=1;i<=n;i++)a[i]+=a[i-1]; |
| for(int i=1;i<=tot;i++)b[a[len[i]]--]=i; |
| } |
| |
| int h[M<<1],e[M<<1],ne[M<<1],cnt; |
| void add(int from,int to) { |
| e[++cnt]=to; ne[cnt]=h[from]; h[from]=cnt; |
| } |
| |
| void build() { |
| scanf("%s",s+1); |
| n=strlen(s+1); |
| for(int i=1;i<=n;i++)insert(s[i]-'a',i); |
| for(int i=2;i<=tot;i++)add(fa[i],i); |
| Sort(); |
| for(int i = tot; i >= 1; i--)siz[fa[b[i]]] += siz[b[i]]; |
| } |
| }SAM; |
单调栈
| void Up_Stk(int n, int a[], int l[], int r[]) { |
| for(int i = 1 |
| int j = i; |
| while(j > 1 && a[j - 1] <= a[i])j = l[j -1]; |
| l[i] = j; |
| } |
| for(int i = n |
| int j = i; |
| while(j < n && a[j + 1] < a[i])j = r[j + 1]; |
| r[i] = j; |
| } |
| } |
可持久化01tire
| struct Lasting_01tire { |
| const int N = 30; |
| struct node { |
| int ch[2], cnt; |
| }tr[M * 32]; |
| int rot[M], tot; |
| void insert(int pre, int &now, int i, int x) { |
| tr[now = ++tot] = tr[pre]; |
| tr[now].cnt++; |
| if(i < 0)return ; |
| int v = x >> i & 1; |
| tr[now].ch[v ^ 1] = tr[pre].ch[v ^ 1]; |
| insert(tr[pre].ch[v], tr[now].ch[v], i - 1, x); |
| } |
| int query(int l, int r, int x) { |
| l = l > 1 ? rot[l - 2] : 0; |
| r = rot[r]; |
| int ans = 0; |
| for(int i = N; i >= 0; i--) { |
| int v = x >> i & 1; |
| if(tr[tr[r].ch[v ^ 1]].cnt - tr[tr[l].ch[v ^ 1]].cnt) { |
| ans += 1 << i; |
| l = tr[l].ch[v ^ 1]; |
| r = tr[r].ch[v ^ 1]; |
| } |
| else { |
| l = tr[l].ch[v]; |
| r = tr[r].ch[v]; |
| } |
| } |
| return ans; |
| } |
| void reset(int n) { |
| for(int i = 0; i <= n + 1; i++)rot[i] = 0; |
| for(int i = 0; i <= tot; i++) |
| tr[i].ch[0] = tr[i].ch[1] = tr[i].cnt = 0; |
| tot = 0; |
| } |
| void build(int n, int sum[]) { |
| reset(n); |
| insert(0, rot[0], N, 0); |
| for(int i = 1; i <= n; i++) |
| insert(rot[i - 1], rot[i], N, sum[i]); |
| } |
| }Tr; |
线段树动态开点
| |
| #define ls(u) tr[u].ls |
| #define rs(u) tr[u].rs |
| #define la(u) tr[u].la |
| #define sum(u) tr[u].sum |
| |
| int cnt=1; |
| struct node { |
| int ls,rs; |
| ll la,sum; |
| }tr[M*45]; |
| |
| void pd(int u,ll len) { |
| if(len<=1)return ; |
| if(!ls(u))ls(u)=++cnt; |
| if(!rs(u))rs(u)=++cnt; |
| sum(ls(u))+=la(u)*(len/2); |
| la(ls(u))+=la(u); |
| sum(rs(u))+=la(u)*(len-len/2); |
| la(rs(u))+=la(u); |
| la(u)=0; |
| } |
| |
| void pu(int u) { |
| sum(u)=sum(ls(u))+sum(rs(u)); |
| } |
| |
| ll query(int l,int r,int u=1,int cl=1,int cr=1e9) { |
| if(cl>=l&&cr<=r)return sum(u); |
| pd(u,cr-cl+1); |
| int mid=(cl+cr-1)/2; |
| ll ans=0; |
| if(mid>=l)ans+=query(l,r,ls(u),cl,mid); |
| if(mid<r)ans+=query(l,r,rs(u),mid+1,cr); |
| return ans; |
| } |
| |
| void up(int l,int r,ll v,int u=1,int cl=1,int cr=1e9) { |
| if(cl>=l&&cr<=r) { |
| sum(u)+=v*(cr-cl+1); |
| la(u)+=v; |
| return ; |
| } |
| pd(u,cr-cl+1); |
| int mid=(cl+cr-1)/2; |
| if(mid>=l)up(l,r,v,ls(u),cl,mid); |
| if(mid<r)up(l,r,v,rs(u),mid+1,cr); |
| pu(u); |
| } |
| |
| void add(int l,int r,int v) { |
| up(l,r,v); |
| } |
| |
| ll que(int l,int r) { |
| return query(l,r); |
| } |
线段树(正确性还有待测试)
| struct Segment { |
| #define ls(u) u<<1 |
| #define rs(u) u<<1|1 |
| #define mx(u) tr[u].mx |
| #define mn(u) tr[u].mn |
| #define la(u) tr[u].la |
| #define len(u) (tr[u].r-tr[u].l+1) |
| #define sum(u) tr[u].sum |
| |
| |
| struct node { |
| int l,r; |
| int la; |
| int mx,mn,sum; |
| }tr[M<<2]; |
| |
| |
| void pu(int u) { |
| sum(u)=sum(ls(u))+sum(rs(u)); |
| mx(u) =max(mx(ls(u)),mx(rs(u))); |
| mn(u) =min(mn(ls(u)),mn(rs(u))); |
| } |
| |
| |
| void update(int u,int v) { |
| sum(u)+=len(u)*v; |
| mx(u)+=v; |
| mn(u)+=v; |
| la(u)+=v; |
| } |
| |
| |
| void pd(int u) { |
| if(la(u)) { |
| update(ls(u),la(u)); |
| update(rs(u),la(u)); |
| la(u)=0; |
| } |
| } |
| |
| |
| void build(int u,int l,int r) { |
| tr[u]={l,r}; |
| if(l==r) { |
| return ; |
| } |
| int mid=(l+r)/2; |
| build(ls(u),l,mid); |
| build(rs(u),mid+1,r); |
| pu(u); |
| } |
| |
| |
| int query(int u,int l,int r) { |
| if(tr[u].l>=l&&tr[u].r<=r) { |
| return 0; |
| } |
| if(tr[u].l>r||tr[u].r<l) { |
| return 0; |
| } |
| pd(u); |
| query(ls(u),l,r); |
| query(rs(u),l,r); |
| return 0; |
| } |
| |
| |
| void up(int u,int l,int r,int v) { |
| if(tr[u].l>=l&&tr[u].r<=r) { |
| update(u,v); |
| return ; |
| } |
| if(tr[u].l>r||tr[u].r<l) { |
| return ; |
| } |
| pd(u); |
| up(ls(u),l,r,v); |
| up(rs(u),l,r,v); |
| pu(u); |
| } |
| |
| |
| void up(int u,int pos,int v) { |
| if(tr[u].l==pos&&tr[u].l==tr[u].r) { |
| |
| return ; |
| } |
| if(tr[u].l>pos||tr[u].r<pos) { |
| return ; |
| } |
| pd(u); |
| up(ls(u),pos,v); |
| up(rs(u),pos,v); |
| pu(u); |
| } |
| }Tr; |
组合数学
| #include <bits/stdc++.h> |
| using namespace std; |
| #define int long long |
| const int M=1e6+5,mod=998244353; |
| |
| int kpow(int a,int b) { |
| int ans=1; |
| while(b) { |
| if(b&1)ans=ans*a%mod; |
| b>>=1; |
| a=a*a%mod; |
| } |
| return ans; |
| } |
| |
| #define inv(x) kpow(x,mod-2) |
| int fact[M],infact[M]; |
| void init(int n=3e5) { |
| fact[0]=1; |
| for(int i=1;i<=n;i++)fact[i]=fact[i-1]*i%mod; |
| infact[n]=inv(fact[n]); |
| for(int i=n-1;i>=0;i--)infact[i]=infact[i+1]*(i+1)%mod; |
| } |
| |
| int C(int a,int b) { |
| if(b<0||a<b)return 0; |
| |
| return fact[a]*infact[b]%mod*infact[a-b]%mod; |
| } |
| |
| void add(int &x,int y) { |
| x=(x%mod+y%mod)%mod; |
| } |
树直径上的点
| void dfs2(int id,int now,int fa) { |
| b[id]=max(b[id],dep[now]); |
| if(fa!=0)v[id].push_back(now); |
| for(int i=h[now];i;i=ne[i]) { |
| int to=e[i]; |
| if(to==fa||st[to])continue; |
| dep[to]=dep[now]+1; |
| dfs2(id,to,now); |
| } |
| } |
| |
| dep[1]=1,dfs1(1,0); |
| dep[root]=1,dfs1(root,0); |
| while(root) { |
| a[++cnt]=root; |
| st[root]=1; |
| root=fa[root]; |
| } |
并查集终极形态
| map<int,int>fa; |
| int find(int x) { |
| return fa[x]==0?x:fa[x]=find(fa[x]); |
| } |
st表二分
| int fun1(int x) { |
| int k=x; |
| for(int i=19;i>=0;i--) { |
| if(k>(1<<i)&&__gcd(a[x],f[k-(1<<i)][i])==a[x]) |
| k-=1<<i; |
| } |
| return k; |
| } |
| |
| int fun2(int x) { |
| int k=x; |
| for(int i=19;i>=0;i--) { |
| if(k+(1<<i)<=n&&__gcd(a[x],f[k+1][i])==a[x]) |
| k+=1<<i; |
| } |
| return k; |
| } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!