int快读(可负数)
inline int read() {
int f=1,x=0;
char ch=getchar();
while(ch<'0'||ch>'9'){
if (ch=='-') f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
x=x*10+ch-'0',ch=getchar();
return f*x;
}
倍增ST表
for (int i=1;i<=n;i++)
f[0][i]=read();
for (int i=1;i<=21;i++)
for (int j=1;j+(1<<i)-1<=n;j++)
f[i][j]=max(f[i-1][j],f[i-1][j+(1<<(i-1))]);
while(m--) {
l=read();r=read();
len=log2(r-l+1);
printf("%d\n",max(f[len][l],f[len][r-(1<<len)+1]));
}
指针线段树
struct note {
ll s,alazy;
note *lson,*rson;
}pool[M<<1],*root=&pool[0];
void Build(note *tre,int l,int r) {
if (l==r) {
tre->s=a[l];
return;
}
int mid=(l+r)>>1;
tre->lson=&pool[++cnt];
tre->rson=&pool[++cnt];
Build(tre->lson,l,mid);
Build(tre->rson,mid+1,r);
tre->s=tre->lson->s + tre->rson->s;
}
inline void pushdown(note *tre,int l,int r) {
if (!tre->alazy) return ;
int mid=(l+r)>>1;
tre->lson->s +=tre->alazy*(mid-l+1);
tre->rson->s +=tre->alazy*(r-mid);
tre->lson->alazy+=tre->alazy;
tre->rson->alazy+=tre->alazy;
tre->alazy=0;
}
void change(note *tre,int l,int r,int x,int y,int d) {
if (x<=l&&y>=r) {
tre->s+=(ll)d*(r-l+1);
tre->alazy+=d;
return;
}
pushdown(tre,l,r);
int mid=(l+r)>>1;
if (x<=mid) change(tre->lson,l,mid,x,y,d);
if (y>mid) change(tre->rson,mid+1,r,x,y,d);
tre->s=tre->lson->s +tre->rson->s;
}
ll query(note *tre,int l ,int r,int x,int y) {
if (x<=l&&y>=r) return tre->s;
pushdown(tre,l,r);
int mid=(l+r)>>1;
ll t1=0,t2=0;
if (x<=mid) t1=query(tre->lson,l,mid,x,y);
if (y>mid) t2=query(tre->rson,mid+1,r,x,y);
return t1+t2;
}
int main() {
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) scanf("%d",&a[i]);
Build(root,1,n);
while(m--) {
scanf("%d",&k);
if (k==1) {
scanf("%d%d%d",&x,&y,&k);
change(root,1,n,x,y,k);
}
else {
scanf("%d%d",&x,&y);
printf("%lld\n",query(root,1,n,x,y));
}
}
return 0;
}
数组线段树
inline ll lson(ll x) {return x<<1;}
inline ll rson(ll x) {return x<<1|1;}
inline void update(ll x) {c[x].sum=c[lson(x)].sum+c[rson(x)].sum;}
inline ll diss(ll x) {return c[x].r-c[x].l+1;}
inline ll mid(ll l,ll r) {return (l+r)>>1;}
inline void pushdown(ll x) {
if (c[x].tag) {
c[lson(x)].sum+=c[x].tag*diss(lson(x));
c[rson(x)].sum+=c[x].tag*diss(rson(x));
c[lson(x)].tag+=c[x].tag;
c[rson(x)].tag+=c[x].tag;
c[x].tag=0;
}
}
void build(ll x,ll l,ll r) {
c[x].l=l;c[x].r=r;
if (l==r) {
c[x].sum=a[l];
return;
}
build(lson(x),l,mid(l,r));
build(rson(x),mid(l,r)+1,r);
update(x);
}
ll query(ll x,ll l,ll r) {
if (c[x].l>=l&&c[x].r<=r)return c[x].sum;
pushdown(x);
ll mi=mid(c[x].l,c[x].r);
ll ans=0;
if (l<=mi)ans+=query(lson(x),l,r);
if (r>mi) ans+=query(rson(x),l,r);
return ans;
}
void change(ll x,ll l,ll r,ll d) {
if (c[x].l>=l&&c[x].r<=r) {
c[x].sum+=d*diss(x);
c[x].tag+=d;
return;
}
pushdown(x);
ll mi=mid(c[x].l,c[x].r);
if (l<=mi) change(lson(x),l,r,d);
if (r>mi) change(rson(x),l,r,d);
update(x);
}
快速幂
ll quick(ll a,ll b) {
ll ans=1,base=a;
while (b>0) {
if (b&1) ans*=base;
base*=base;
b>>=1;
}
return ans;
}
逆元(包括扩欧)
int exgcd(int a,int b,int &x,int &y) {
if (b==0) {
x=1;
y=0;
return a;
}
int d=exgcd(b,a%b,y,x);
y-=(a/b)*x;
return d;
}
int inv(int a,int b) {
int x,y;
if (exgcd(a,b,x,y)!=1) return -1;
else return (x%b+b)%b;
}
线性筛法
for (int i=2;i<=n;i++) {
if (book[i]) prime[++cnt]=i;
for (int j=1;j<=cnt&&i*prime[j]<=n;j++) {
book[i*prime[j]]=0;
if (i%prime[j]==0) break;
}
}
vector建图
struct Edge {
int from, to, dist;
Edge() {}
Edge(int _from, int _to, int _dist): from(_from), to(_to), dist(_dist) {}
};
vector<Edge> g[MAXN];
for (vector<Edge>::iterator it = g[now].begin(); it != g[now].end(); it++) {
printf("%d\n", it->to);
}
链式前向星建树
inline void add (int _u,int _v) {
head[++cnt]=_v;
Next[cnt]=fat[_u];
fat[_u]=cnt;
}
//head 子树节点 fat 父亲节点 Next :D
倍增LCA
void dfs(int u) {
for (int x=fat[u];x;x=Next[x]) {
if (v[x]==f[0][u]) continue;
d[v[x]]=d[u]+1;
f[0][v[x]]=u;
dfs(v[x]);
}
}
void build() {
for (int i=1;i<=19;i++)
for (int j=1;j<=n;j++)
f[i][j]=f[i-1][f[i-1][j]];
}
inline int query(int x,int y) {
if (d[x]>d[y])swap(x,y);
int delta=d[y]-d[x];
for (int i=18;i>=0;i--)
if (delta>=(1<<i)) y=f[i][y],delta-=(1<<i);
if (x==y)return x;
for (int i=19;i>=0;i--)
if (f[i][x]!=f[i][y])
x=f[i][x],y=f[i][y];
return f[0][x];
}
树剖LCA
void dfs1(int u) {
siz[u]=1;
for (int x=head[u];x;x=nex[x] ) {
int v=ver[x];
if(v!=fa[u]) {
dep[v]=dep[u]+1;
fa[v]=u;
dfs1(v);
siz[u]+=siz[v];
if (siz[v]>siz[son[u]]) son[u]=v;
}
}
}
void dfs2(int u,int t) {
id[u]=++tot;
cur[tot]=a[u];
top[u]=t;
if (son[u]) dfs2(son[u],t);
for (int x=head[u];x;x=nex[x]) {
int v=ver[x];
if (v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
inline int LCA(int a,int b) {
while (top[a]!=top[b]) {
if (dep[top[a]]<dep[top[b]]) swap(a,b);
a=fa[top[a]];
}
if (dep[a]>dep[b]) return b;
else return a;
}
并查集-路径压缩
int getf(int x) {
if (f[x]=x) return x;
return f[x]=getf(f[x]);
}
inline void merge(int a,int b) {
int t1=getf(a),t2=getf(b);
if (t1!=t2) f[t1]=t2;
}
优先队列优化--Dijstra
struct note {
int to,nex,dis;
}edge[M];
inline void add(int a,int b,int d) {
edge[++cnt].nex=head[a];
edge[cnt].dis=d;
edge[cnt].to=b;
head[a]=cnt;
}
typedef pair<int,int> node;
priority_queue<node,vector<node>,greater<node> >q;
void dij() {
for (int i=1;i<=n;i++)
if (i!=s) {
dis[i]=inf;
q.push(node(dis[i],i));
}
q.push(node(dis[s]=0,s));
while(!q.empty()) {
int minn=q.top().first,mi=q.top().second;
q.pop();
if (vis[mi]) continue;
vis[mi]=1;
for (int i=head[mi];i;i=edge[i].nex) {
int e=edge[i].to;
if (minn+edge[i].dis<dis[e]){
dis[e]=minn+edge[i].dis;
q.push(node(dis[e],e));
}
}
}
}
最小生成树--Kruskal
struct note {
int u,v,d;
}edge[M];
inline bool cmp(note a,note b) {return a.d<b.d;}
int getf(int x) {
if (f[x]==x) return x;
return f[x]=getf(f[x]);
}
inline bool judge(int a,int b){return getf(a)==getf(b);}
inline void kruskal() {
sort(edge,edge+n,cmp);
for (int i=1;i<=m;i++) {
if (judge(edge[i].u,edge[i].v)) continue;
ans+=edge[i].d;
f[edge[i].v]=edge[i].u;
if (++cnt==n-1) break;
}
背包问题
for (int i=1;i<=n;i++)
for (int j=v;j>=w[i];j--)
f[j]=max(f[j],f[j-w[i]]+val[i]);
//01背包
for (int i=0;i<=n;i++)
for (int j=w[i];j<=v;j++)
f[j]=max(f[j],f[j-w[i]]+val[i]);
//无限背包
void pre() {
for (int i=1;i<=n;i++) {
int x=1;
while (pi[i]) {
t[++top]=ti[i]*x;
p[top]=ci[i]*x;
pi[i]-=x;
x*=2;
if (pi[i]<=x) {
t[++top]=ti[i]*pi[i];
p[top]=ci[i]*pi[i];
break;
}
}
}
}
缩点 Tarjan
void tarjan(int u) {
dfn[u]=low[u]=++num;
st[++top]=u;
for (int i=head[u];i;i=edge[i].nex) {
int v=edge[i].to;
if (!dfn[v]) { //! ?
tarjan(v);
low[u]=min(low[u],low[v]);
}
else {
if (!co[v])
low[u]=min(low[u],dfn[v]);
}
}
if (low[u]==dfn[u]) {
co[u]=++col;
sii[col]++;
while(st[top]!=u) {
co[st[top]]=col;
top--;
}
top--;
}
}