tarjan
namespace trj{
const int maxn=1e5+5;
const int maxm=2e5+5;
struct EDGE{
EDGE *next;
int to,val;
}e[maxm*4];
int etot=0;
EDGE *node[maxn*2];
int nv[maxn*2];
void add(int x,int y,int val){
e[++etot].next=node[x];
node[x]=e+etot;
e[etot].to=y;
e[etot].val=val;
}
void clear(){
memset(node,0,sizeof(node));
memset(nv,0,sizeof(nv));
etot=0;
}
bool use[maxn];
int dfn[maxn],low[maxn],col[maxn],stk[maxn],top,tot,colnum;
void dfs(int x,int fa){
low[x]=dfn[x]=++tot;
use[x]=true;
stk[++top]=x;
for(EDGE *i=node[x];i;i=i->next)if(i->to!=fa){
if(!dfn[i->to]){
dfs(i->to,x);
low[x]=std::min(low[x],low[i->to]);
}else if(use[i->to])low[x]=std::min(low[x],dfn[i->to]);
}else fa=0;
if(dfn[x]==low[x]){
col[x]=++colnum;
use[x]=false;
while(stk[top]!=x){
use[stk[top]]=false;
col[stk[top]]=colnum;
top--;
}
top--;
}
}
void tarjan(int n){
memset(dfn,0,sizeof(dfn));
tot=0;
colnum=n;
for(int i=1;i<=n;i++)if(!dfn[i])dfs(i,0);
for(int x=1;x<=n;x++){
nv[col[x]]+=nv[x];
for(EDGE *i=node[x];i;i=i->next)
if(col[x]!=col[i->to])add(col[x],col[i->to],i->val);
}
}
}
線段樹(區間求和區間加爲例)
template<typename tp,typename tpc=tp>
class segment_tree{
#define lson l,mid,rt<<1 //簡化操作
#define rson mid+1,r,rt<<1|1
private:
int maxn_seg; //設置線段樹長度
tp *sum; //線段樹節點所存權值的和
tpc *col; //線段樹標記
void updata(int l,int r,int rt){ //更新當前節點的值(自下向上)
sum[rt]=(sum[rt<<1]+sum[rt<<1|1]);
}
void clear(tpc &x){ //清空節點標記
x=0;
}
void color(int l,int r,int rt,tpc colv){ //標記節點
col[rt]+=colv;
sum[rt]+=(r-l+1)*colv;
}
void pushcol(int l,int r,int rt){ //下放當前節點的標記
int mid=(l+r)>>1;
if(col[rt]){
color(lson,col[rt]);
color(rson,col[rt]);
}
clear(col[rt]); //下放後清除標記
}
public:
segment_tree(int N){ //初始化線段樹長度
maxn_seg=N+1;
sum=new tp[maxn_seg<<2];
col=new tpc[maxn_seg<<2];
}
~segment_tree(){
delete[]sum;
delete[]col;
}
void build(int l,int r,int rt,tp *orv){ //初始化線段樹
clear(col[rt]); //初始化標記
if(l==r){
sum[rt]=orv[l]; //初始化權值
return;
}
int mid=(l+r)>>1;
build(lson,orv);
build(rson,orv);
updata(l,r,rt);
}
void modify(int l,int r,int rt,int tl,int tr,tpc colv){ //區間[tl,tr]進行colv類型的修改
if(tl<=l&&tr>=r){
color(l,r,rt,colv);
return;
}
pushcol(l,r,rt);
int mid=(l+r)>>1;
if(tl<=mid)modify(lson,tl,tr,colv);
if(tr>mid)modify(rson,tl,tr,colv);
updata(l,r,rt);
}
tp query(int l,int r,int rt,int tl,int tr){ //對區間[tl,tr]進行查詢
if(tl<=l&&tr>=r)return sum[rt];
pushcol(l,r,rt);
int mid=(l+r)>>1;
if(tl<=mid&&tr>mid)return query(lson,tl,tr)+query(rson,tl,tr);
else if(tl<=mid)return query(lson,tl,tr);
else return query(rson,tl,tr);
}
#undef lson
#undef rson
};
樹狀數組優化版(區間操作和修改)
template<typename tp>
class bit_pro{
#define lowbit(a) (a&(-a)) //lowbit函數
private:
int maxn_bit; //樹狀數組長度
tp *val1,*val2; //同時處理兩組數以進行區間操作
void add(tp *val,int pos,tp v){ //更改單一數組前綴和
for(int i=pos;i<=maxn_bit;i+=lowbit(i))val[i]+=v;
}
tp get(tp *val,int pos){ //求到單一數組前綴和
tp tans=0;
for(int i=pos;i;i-=lowbit(i))tans+=val[i];
return tans;
}
tp sum(int pos){ //得到最終數組前綴和
return (pos+1)*get(val1,pos)-get(val2,pos);
}
public:
bit_pro(int N){ //初始化
maxn_bit=N;
val1=new tp[maxn_bit+1]; //長度要加1
val2=new tp[maxn_bit+1];
std::memset(val1,0,sizeof(tp)*(maxn_bit+1)); //對指針操作,要指明操作長度
std::memset(val2,0,sizeof(tp)*(maxn_bit+1));
}
~bit_pro(){
delete [] val1;
delete [] val2;
}
tp query(int l,int r){ //查詢區間和
return sum(r)-sum(l-1);
}
void modify(int l,int r,tp v){ //區間更改
add(val1,l,v);
add(val1,r+1,-v);
add(val2,l,v*l);
add(val2,r+1,-v*(r+1));
}
#undef lowbit
};
樹狀數組普通版
template<typename tp>
class bit{
#define lowbit(a) (a&(-a))
private:
int maxn_bit;
tp *val;
public:
bit(int N){
maxn_bit=N;
val=new tp[maxn_bit+1];
std::memset(val,0,sizeof(tp)*(maxn_bit+1));
}
~bit(){
delete [] val;
}
void add(int pos,tp v){
for(int i=pos;i<=maxn_bit;i+=lowbit(i))val[i]+=v;
}
tp get(int pos){
tp tans=0;
for(int i=pos;i;i-=lowbit(i))tans+=val[i];
return tans;
}
#undef lowbit
};
st表
template<typename tp>
class ST{
private:
int maxn_st;
tp **val;
int *pow2;
int *lg2;
int max_bit;
public:
ST(int N,tp *v){
maxn_st=N+1;
max_bit=0;
while((1<<max_bit++)<maxn_st);
max_bit++;
val=new tp*[max_bit];
for(int i=0;i<max_bit;i++)val[i]=new tp[maxn_st];
pow2=new int[max_bit];
lg2=new int[maxn_st];
lg2[0]=-1;
for(int i=1;i<maxn_st;i++)lg2[i]=lg2[i/2]+1;
pow2[0]=1;
for(int i=1;i<max_bit;i++ )pow2[i]=pow2[i-1]*2;
return;
for(int i=1;i<maxn_st;i++)val[0][i]=v[i];
for(int i=1;i<max_bit;i++)
for(int j=1;j<maxn_st;j++)
if(j+pow2[i]-1<maxn_st)
val[i][j]=std::max(val[i-1][j],val[i-1][j+pow2[i-1]]);
}
~ST(){
for(int i=0;i<max_bit;i++)delete [] val[i];
delete [] val;
delete [] pow2;
delete [] lg2;
}
tp query(int l,int r){
int k=lg2[r-l+1];
return std::max(val[k][l],val[k][r-pow2[k]+1]);
}
};
trie樹
template<typename tp,typename tpv=int>
class trie{
#define maxn_c 26
private:
struct node{
node **son=new node*[maxn_c];
tpv val;
node(){
memset(son,0,sizeof(node*)*maxn_c);
val=0;
}
};
public:
node *root=new node;
inline int cal(tp S){
return *S-'a';
}
void insert(node *x,tp S){
if(*S==0){
x->val++;
return;
}
int v=cal(S);
if(!x->son[v])x->son[v]=new node;
insert(x->son[v],S+1);
}
void query(node *x,tp S){
if(!S[dep])return;
int v=cal(S+dep);
if(x->son[v])query(x->son[v],S+1);
}
#undef maxn_c
};
manacher
template<typename tp>
class manacher{
private:
tp *S;
int *r,tot;
void transform(tp *bg,tp *ed){
S[0]='!';
S[1]='#';
tot=2;
for(tp *i=bg;i!=ed;i++){
S[tot++]=*i;
S[tot++]='#';
}
S[tot]=0;
}
int work(){
int maxright=-1,mid;
for(int i=0;i<tot;i++){
if(i<maxright)r[i]=std::min(r[mid*2-i],maxright-i);
else r[i]=1;
for(;S[i+r[i]]==S[i-r[i]];r[i]++);
if(i+r[i]>maxright){
mid=i;
maxright=i+r[i];
}
}
int ans=0;
for(int i=0;i<tot;i++)ans=std::max(ans,r[i]-1);
return ans;
}
public:
manacher(int N){
r=new int[(N+5)<<1];
S=new tp[(N+5)<<1];
}
~manacher(){
delete [] r;
delete [] S;
}
int solve(tp *bg,tp *ed){
transform(bg,ed);
return work();
}
};
FFT
#define tpv double
class cpx{
public:
tpv r,i;
cpx(tpv a=0.0,tpv b=0.0){
r=a,i=b;
}
cpx operator *(const cpx &p)const{
return cpx(r*p.r-i*p.i,r*p.i+i*p.r);
}
cpx operator +(const cpx &p)const{
return cpx(r+p.r,i+p.i);
}
cpx operator -(const cpx &p)const{
return cpx(r-p.r,i-p.i);
}
cpx operator /(const tpv &p)const{
return cpx(r/p,i/p);
}
};
#undef tpv
template<typename tp,typename tpv=double>
class FFT{
#define pi 3.14159265359
private:
int n;
tp *omega=NULL;
tp *A=NULL,*B=NULL;
void getomega(){
delete [] omega;
omega=new tp[n];
for(int i=0;i<n;i++)omega[i]=tp(cos(2.0*pi/n*i),sin(2.0*pi/n*i));
}
void DFT(tp *v,tpv ck){
for(int l=2;l<=n;l<<=1){
int m=l/2;
for(tp *p=v;p!=v+n;p+=l)
for(int i=0;i<m;i++){
tp t=tp(omega[n/l*i].r,omega[n/l*i].i*ck)*p[i+m];
p[i+m]=p[i]-t;
p[i]=p[i]+t;
}
}
}
tp* getval(tp *bg,tp *ed){
tp *val=new tp[n];
for(int i=0;i<n;i++)if(i<ed-bg)val[i]=bg[i];
else val[i]=tp(0.0,0.0);
return val;
}
void reverse(tp *val){
int k=0;
while((1<<k)<n)k++;
for(int i=0;i<n;i++){
int t=0;
for(int j=0;j<k;j++)if(i&(1<<j))t|=(1<<(k-j-1));
if(i<t)std::swap(val[i],val[t]);
}
}
public:
tp *solve(tp *bg_A,tp *ed_A,tp *bg_B,tp *ed_B){
int tpn=ed_A-bg_A+ed_B-bg_B-1;
n=1;
while(n<tpn)n<<=1;
getomega();
A=getval(bg_A,ed_A);
B=getval(bg_B,ed_B);
reverse(A);
reverse(B);
DFT(A,1);
DFT(B,1);
for(int i=0;i<n;i++)A[i]=A[i]*B[i];
reverse(A);
DFT(A,-1);
for(int i=0;i<n;i++)A[i]=A[i]/n;
tp *ans=new tp[n];
memcpy(ans,A,sizeof(tp)*n);
delete[] A;
delete[] B;
return ans;
}
#undef pi
};
矩陣乘法及快速冪
template<typename tp>
class Matrix{
public:
unsigned int n,m;
tp **val;
void clear(){
for(int i=0;i<n;i++)
memset(val[i],0,sizeof(tp)*m);
}
Matrix(int N,int M){
n=N,m=M;
val=new tp*[N];
for(int i=0;i<N;i++)val[i]=new tp[M];
clear();
}
~Matrix(){
for(int i=0;i<n;i++)delete [] val[i];
delete [] val;
}
Matrix operator *(const Matrix &p)const{
Matrix tv(n,p.m);
for(int i=0;i<n;i++)
for(int j=0;j<p.m;j++)
for(int k=0;k<m;k++){
tv.val[i][j]+=val[i][k]*p.val[k][j];
}
return tv;
}
void print(){
for(int i=0;i<n;i++){
for(int j=0;j<m;j++)printf("%d ",val[i][j]);
printf("\n");
}
}
};
template<typename tp=int>
Matrix<tp> pow2(Matrix<tp> x,int p){
Matrix<tp> ans(x.n,x.m);
for(int i=0;i<x.n;i++)ans.val[i][i]=1;
for(;p;p>>=1,x=x*x)if(p&1)ans=ans*x;
return ans;
}