树状数组
int tr[N],n;
void update(int pos,int val){
while(pos<=n){
tr[pos]+=val;
pos+=pos&(-pos);
}
}
int query(int l,int r){
int ansl=0,ansr=0;l--;
while(l>0){
ansl+=tr[l];
l-=l&(-l);
}
while(r>0){
ansr+=tr[r];
r-=r&(-r);
}
return ansr-ansl;
}
线段树(单点更新)
int tr[4*N];
void update(int rt,int L,int R,int pos,int val){
if(L==R){
tr[rt]=f;return;
}
int mid=L+R>>1;
if(pos<=mid)update(rt,L,mid,pos,val);
else update(rt,mid+1,R,pos,val);
tr[rt]=max(tr[ls],tr[rs]);
}
int Query(int rt,int L,int R,int l,int r){
if(y>=r&&x<=l)return tr[rt];
int mid=l+r>>1;
int ans=0;
if(l<=mid)ans=Query(ls,L,mid,l,r);
if(r>mid)ans=max(ans,Query(ts,mid+1,R,l,r));
return ans;
}
线段树(区间更新)
int tr[N*4];
int f[N*4];
void down(int rt){
if(!f[rt])return;
f[ls]+=f[rt];f[rs]+=f[rt];
tr[ls]+=f[rt],tr[rs]+=f[rt];
f[rt]=0;
}
void update(int rt,int L,int R,int l,int r,int val){
if(R<=r&&L>=l){
tr[rt]+=val;f[rt]+=val;return;
}
down(rt);
int mid=R+L>>1;
if(l<=mid)update(ls,L,mid,l,r,val);
if(r>mid)update(rs,mid+1,R,l,r,val);
tr[rt]=max(tr[ls],tr[rs]);
}
int query(int rt,int L,int R,int l,int r){
if(r>=R&&l<=L){return tr[rt];}
down(rt);
int ans=0;
int mid=R+L>>1;
if(l<=mid)ans=query(ls,L,mid,l,r);
if(r>mid)ans=max(ans,query(rs,mid+1,R,l,r));
return ans;
}
矩阵
#define MOD ((int)1e9+7)
struct matrix{
int size;
LL mat[N][N];
matrix(int s){
size=s;memset(mat,0,sizeof(mat));
}void init(){
for(int i=1;i<=size;i++){
for(int j=1;j<=size;j++){
scanf("%lld",&mat[i][j]);
}
}
}void out(){
for(int i=1;i<=size;i++){
for(int j=1;j<=size;j++){
printf("%lld ",mat[i][j]);
}printf("\n");
}
}matrix operator * (const matrix & x)const{
matrix ans(x.size);
for(int i=1;i<=x.size;i++){
for(int j=1;j<=x.size;j++){
for(int k=1;k<=x.size;k++){
ans.mat[i][j]=(ans.mat[i][j]+mat[i][k]*x.mat[k][j])%MOD;
}
}
}return ans;
}
} ;
matrix swift(matrix a,int t){
matrix ans(a.size);
for(int i=1;i<=a.size;i++)ans.mat[i][i]=1;
while(t){
if(t&1)ans=ans*a;
a=a*a;t>>=1;
}return ans;
}
带权并查集
int fa[maxn],v[maxn];
int fi(int a){
if(fa[a]==a)return a;
int tmp=fa[a];
fa[a]=fi(fa[a]);
v[a]+=v[tmp];
return fa[a];
}
int un(int a,int b,int s){
int f1=fi(a),f2=fi(b);
if(f1==f2){
if(s+v[b]==v[a])return 0;
return 1;
}
fa[f1]=f2;v[f1]=s+v[b]-v[a];
return 0;
}
LCA
int head[100009];
int to[400009],nex[400009],v[400009];
int now;
void add(int a,int b,int c1,int c2){
to[++now]=b;v[now]=c1;nex[now]=head[a];head[a]=now;
to[++now]=a;v[now]=c2;nex[now]=head[b];head[b]=now;
}
int up[100009],down[100009];
int fa[100009];
int deep[100009];
void dfs(int p,int f,int t){
fa[p]=f;deep[p]=t;
for(int i=head[p];~i;i=nex[i]){
int b=to[i];
if(b==f)up[p]=up[f]+v[i];
}
for(int i=head[p];~i;i=nex[i]){
int b=to[i];
if(b!=f){
down[b]=down[p]+v[i];
dfs(b,p,t+1);
}
}
}
int p[100009][30];
void init(int n){
mmm(p,-1);
for(int i=1;i<=n;i++)p[i][0]=fa[i];
for(int i=1;;i++){
int bre=1;
for(int j=1;j<=n;j++){
if(~p[j][i-1]){
bre=0;p[j][i]=p[p[j][i-1]][i-1];
}
}
if(bre)break;
}
}
int lca(int a,int b){
if(deep[a]>deep[b])swap(a,b);
int i;
for(i=0;(1<<i)<deep[b];i++);i--;
for(;;){
if(deep[a]==deep[b])break;
if(deep[b]-deep[a]<(1<<i))i--;
else b=p[b][i];
}
for(i=0;(1<<i)<deep[b];i++);i--;
for(;;){
if(a==b)return a;
if(fa[a]==fa[b])return fa[a];
if(p[a][i]==p[b][i])i--;
else a=p[a][i],b=p[b][i];
}
}
int main(){
int t=read();
while(t--){
int n=read();
mmm(head,-1);now=0;
int sum=0;
for(int i=1;i<n;i++){
int a,b,c1,c2;
scanf("%d%d%d%d",&a,&b,&c1,&c2);
add(a,b,c1,c2);sum+=c1+c2;
}
up[1]=down[1]=0;
dfs(1,-1,1);
init(n);
...
}
}
树分治
const int N =10009;
int n,k;
int head[N],nex[2*N],to[2*N],from[2*N],v[2*N],now;
void add(int a,int b,int vv){
to[++now]=b;v[now]=vv;from[now]=a;nex[now]=head[a];head[a]=now;
to[++now]=a;v[now]=vv;from[now]=b;nex[now]=head[b];head[b]=now;
}
int ans;
int G;
int vis[N];
int siz[N],maxn[N];
void getG(int p,int fa,int sum){
siz[p]=1;
maxn[p]=0;
for(int i=head[p];~i;i=nex[i]){
if(!vis[to[i]]&&to[i]!=fa){
getG(to[i],p,sum);
siz[p]+=siz[to[i]];
maxn[p]=max(maxn[p],siz[to[i]]);
}
}
maxn[p]=max(maxn[p],sum-siz[p]);
if(maxn[G]>maxn[p])G=p;
}
int dep[N],num,len[N];
void dfs(int p,int fa){
for(int i=head[p];~i;i=nex[i]){
if(vis[to[i]]||fa==to[i])continue;
len[++num]=dep[to[i]]=dep[p]+v[i];
dfs(to[i],p);
}
}
int cal(int p,int length){
int sum=0;
num=0;
len[++num]=dep[p]=length;
dfs(p,0);
sort(len+1,len+1+num);
for(int l=1,r=num;r>l;){
if(dep[r]+dep[l]<=k)sum+=r-l,l++;
else r--;
}
return sum;
}
void divide(int p){
vis[p]=1;
ans+=cal(p,0);
for(int i=head[p];~i;i=nex[i]){
if(vis[to[i]])continue;
ans-=cal(to[i],v[i]);
G=0;
maxn[0]=siz[to[i]];
getG(to[i],0,siz[to[i]]);
divide(G);
}
}
int main(){
while(cin>>n>>k){
if(!n&&!k)break;
ans=0;mmm(head,-1);now=0;mmm(vis,0);
for(int i=1,a,b,v;i<n;i++)a=read(),b=read(),v=read(),add(a,b,v);
maxn[0]=n;
G=0;getG(1,0,n);
divide(G);
printf("%d\n",ans);
}
}
主席树(小于等于k的数量)
const int N=100009;
int rt[N<<2],ls[N<<2],rs[N<<2],cnt,siz[N<<2];
int arr[N],tmp[N];
void insert(int last,int now,int l,int r,int p){
siz[now]=siz[last]+1;
ls[now]=ls[last];
rs[now]=rs[last];
if(l==r) return ;
int mid=l+r>>1;
if(p<=mid)insert(ls[last],ls[now]=++cnt,l,mid,p);
else insert(rs[last],rs[now]=++cnt,mid+1,r,p);
}
int query(int p,int l,int r,int k){
if(r<=k)return siz[p];
int mid=l+r>>1;
int ans=query(ls[p],l,mid,k);
if(k>mid) ans+=query(rs[p],mid+1,r,k);
return ans;
}
int main(){
int t;scanf("%d",&t);
int ca=0;
while(t--){
printf("Case %d:\n",++ca);
cnt=0;memset(siz,0,sizeof(siz));
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&arr[i]);tmp[i]=arr[i];
}
sort(tmp+1,tmp+1+n);
int tt=unique(tmp+1,tmp+1+n)-tmp-1;
for(int i=1;i<=n;i++)insert(rt[i-1],rt[i]=++cnt,1,tt,lower_bound(tmp+1,tmp+1+tt,arr[i])-tmp);
while(m--){
int l,r,k;scanf("%d%d%d",&l,&r,&k);l++,r++;
if(k>=tmp[tt])k=tt;
else k=upper_bound(tmp+1,tmp+1+tt,k)-tmp-1;
if(!k)printf("0\n");
else printf("%d\n",query(rt[r],1,tt,k)-query(rt[l-1],1,tt,k));
}
}
}
主席树(第k大)
#define N 100005
int root[N];
int size[N*25],lchild[N*25],rchild[N*25];
int tot;
void insert(int last,int cur,int L,int R,int k)
{
size[cur]=size[last]+1;
lchild[cur]=lchild[last];
rchild[cur]=rchild[last];
if(L==R)return ;
int mid=L+R>>1;
if(k<=mid) insert(lchild[last],lchild[cur]=++tot,L,mid,k);
else insert(rchild[last],rchild[cur]=++tot,mid+1,R,k);
}
int query(int last,int cur,int k,int L,int R)
{
if(L==R)return L;
int mid=L+R>>1;
int lsum=size[lchild[cur]]-size[lchild[last]];
if(lsum>=k)return query(lchild[last],lchild[cur],k,L,mid);
else return query(rchild[last],rchild[cur],k-lsum,mid+1,R);
}
int a[N],b[N],n,m,l,r,k;
map<int,int>mp;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
tot=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),b[i]=a[i];
sort(b+1,b+n+1);
int t=unique(b+1,b+n+1)-b-1;
for(int i=1;i<=n;i++)insert(root[i-1],root[i]=++tot,1,t,lower_bound(b+1,b+t+1,a[i])-b);
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",b[query(root[l-1],root[r],k,1,t)]);
}
}
}
KMP
void KMP(char *x,int *fail){
int len=strlen(x);
int i=0,j=-1;
fail[0]=-1;
while(i<len){
while(j!=-1&&x[i]!=x[j]) j=fail[j];
fail[++i]=++j;
if(x[i]==x[j]) fail[i]=fail[j];
}
}
int mina(){
int len=strlen(a);
int en=strlen(str);
KMP(str,fail);
int j=0;
for(int i=0;i<len;i++){
while(str[j]!=a[i]&&j!=-1)j=fail[j];
j++;
if(j==en){此小串完全匹配成功}
}
}
AC自动机
#include<stdio.h>
#include<string.h>
#include<queue>
#include<string>
#include<iostream>
#define maxlen 100005
using namespace std;
int n;
int nxt[maxlen][30],FAIL[maxlen],edd[maxlen],root,L;
int mark[maxlen];
int newnode() {
for(int i=0;i<26;i++)
nxt[L][i]=-1;
edd[L]=0;
mark[L]=0;
return L++;
}
void init() {
L=0;
root=newnode();
}
void insert(char buf[],int l){
int now=root;
for(int i=0;i<l;i++) {
if(nxt[now][buf[i]-'a']==-1)nxt[now][buf[i]-'a']=newnode();
now=nxt[now][buf[i]-'a'];
}
edd[now]++;
}
void build(){
queue<int>que;
for(int i=0;i<26;i++) {
if(nxt[root][i]==-1)nxt[root][i]=root;
else {
FAIL[nxt[root][i]]=root;
que.push(nxt[root][i]);
}
}
while(!que.empty()) {
int now=que.front();
que.pop();
for(int i=0;i<26;i++) {
if(nxt[now][i]==-1)
nxt[now][i]=nxt[FAIL[now]][i];
else {
FAIL[nxt[now][i]]=nxt[FAIL[now]][i];
que.push(nxt[now][i]);
}
}
}
}
int query(char buf[],int l) {
int now=root;
int res=0;
for(int i=0;i<l;i++) {
now=nxt[now][buf[i]-'a'];
int temp=now;
while(temp!=root&&mark[temp]==0){
res+=edd[temp];
edd[temp]=0;
mark[temp]=1;
temp=FAIL[temp];
}
}
return res;
}
char buf[maxlen],ans[maxlen];
string A[maxlen];
int main(){
int T;
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
init();
int ma=0;
for(int i=0;i<n;i++) {
scanf("%s",buf);
int l=strlen(buf);
if(ma<l) {
ma=l;
strcpy(ans,buf);
}
insert(buf,l);
}
build();
int sum=query(ans,ma);
if(sum==n) puts(ans);
else puts("No");
}
}
Splay
int ch[N][2],pre[N],cnt[N],size[N],key[N];
int tot,root;
int a[N],n;
void newnode(int &u,int fa,int KEY){
u=++tot;
ch[u][0]=ch[u][1]=0;
pre[u]=fa;cnt[u]=size[u]=1;
key[u]=KEY;
}
void up(int x){
if(x) {
size[x]=cnt[x];
if(ch[x][0])size[x]+=size[ch[x][0]];
if(ch[x][1])size[x]+=size[ch[x][1]];
}
}
void rotate(int u,int kind){
int fa=pre[u];
ch[fa][kind]=ch[u][!kind];
pre[ch[u][!kind]]=fa;
if(pre[fa])ch[pre[fa]][ch[pre[fa]][1]==fa]=u;
pre[u]=pre[fa];
ch[u][!kind]=fa;
pre[fa]=u;
up(fa);up(u);
}
void splay(int u,int goal){
int fa,kind;
while(pre[u]!=goal){
if(pre[pre[u]]==goal) {
rotate(u,R(pre[u])==u);
}
else {
fa=pre[u];
kind=R(pre[fa])==fa;
if(ch[fa][kind]!=u) {
rotate(u,!kind);
rotate(u,kind);
}
else {
rotate(fa,kind);
rotate(u,kind);
}
}
}
up(u);
if(goal==0)root=u;
}
void insert(int v){
if(root==0) {
newnode(root,0,v);
return;
}
int now=root,fa=0;
while(1) {
if(key[now]==v){
cnt[now]++;up(now);up(fa);splay(now,0);
break;
}
fa=now;
now=ch[now][key[now]<v];
if(now==0) {
newnode(ch[fa][key[fa]<v],fa,v);
up(fa);splay(ch[fa][key[fa]<v],0);
break;
}
}
}
int getkth(int u,int k){
int s=size[L(u)]+cnt[u];
if(size[L(u)]<k&&k<=s) return u;
if(s-cnt[u]>=k) return getkth(L(u),k);
else return getkth(R(u),k-s);
}
int find(int u,int x){
if(key[u]==x)return u;
if(key[u]>x) {
if(!L(u))return -1;
return find(L(u),x);
}
if(key[u]<x) {
if(!R(u))return -1;
return find(R(u),x);
}
}
int getpre(int u){
if(cnt[u]>=2)return u;
u=L(u);
while(R(u))u=R(u);
return u;
}
int getnext(int u){
if(cnt[u]>=2)return u;
u=R(u);
while(L(u))u=L(u);
return u;
}
void del(int x){
if(size[root]==1) {
root=0;
return ;
}
if(cnt[x]>1){
cnt[x]--;
return ;
}
splay(x,0);
if(L(root)) {
if(!R(root)) {
pre[L(root)]=0;
root=L(root);
return ;
}
int p=getpre(x);
splay(p,root);
R(p)=R(root);
pre[R(root)]=p;
root=p;
pre[p]=0;
up(root);
}
else{
root=R(root);
pre[root]=0;
}
}