最近公共祖先LCA
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int N=1e4+5;
int t,n,ans;
int pre[N],vis[N];
vector<int> ve[N];
vector<int> que[N];
int find(int x)
{
return pre[x]==x?x:find(pre[x]);
//从下往上的改变顺序,没改变的转折点就是lca
}
void init()
{
for(int i=1;i<=n;i++){
pre[i]=i;
vis[i]=0;
ve[i].clear();
que[i].clear();
}
}
void dfs(int u,int fa)
{
vis[u]=1;
for(int i=0;i<ve[u].size();i++){
int v=ve[u][i];
dfs(v,u);//到叶结点时结束一次
}
for(int j=0;j<que[u].size();j++){//是目标才进行
int v=que[u][j];
ans=find(v);
}
pre[u]=fa;
}
int main()
{
scanf("%d",&t);
while(t--){
scanf("%d",&n);
init();
int x,y;
for(int i=0;i<n-1;i++){
scanf("%d%d",&x,&y);
ve[x].push_back(y);//重点,搭树
vis[y]=1;
}
scanf("%d%d",&x,&y);
que[x].push_back(y);//que存放查询对象
que[y].push_back(x);
for(int i=1;i<=n;i++){
if(vis[i]==0){
memset(vis,0,sizeof(vis));
dfs(i,-1);
break;
}
}
printf("%d\n",ans);
}
return 0;
}
区间最值查询RMQ
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const int N=1e6+5;
int minn[N][25];
int n,m;
void rmq(int n)
{
for(int j=1;j<=25;j++)
for(int i=1;i+(1<<(j-1))-1<=n;i++)
minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
return ;
}
void query(int i,int j)
{
int k=log2(j-i+1.0);
int mina=min(minn[i][k],minn[j-(1<<k)+1][k]);
printf("%d\n",mina);
}
int main()
{
int i,j;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&minn[i][0]);
rmq(n);
scanf("%d",&m);
while(m--){
scanf("%d%d",&i,&j);
query(i,j);
}
return 0;
}
最长回文子串manacher
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=11e4+10;
char str[N<<1];
int p[N<<1];
int main()
{
while(scanf("%s",str)!=EOF&&strlen(str))
{
int len=strlen(str);
for(int i=len;i>=0;i--)
{
str[2*i+2]=str[i];
str[2*i+1]='#';
}
str[0]='$';
len=2*len;
int id=0,mx=0,res=0;
for(int i=0;i<=len;i++){
if(i<mx)
p[i]=min(p[2*id-i],mx-i);
else
p[i]=1;
while(str[i+p[i]]==str[i-p[i]])
p[i]++;
if(p[i]+i>mx){
mx=p[i]+i;
id=i;
}
if(p[i]>res) res=p[i];
}
/*
for(int i=0;i<=len;i++)
printf("%d -> %c ->%d\n",i,str[i],p[i]);
*/
printf("%d\n",res-1);
}
return 0;
}
字符串查找KMP
#include<cstdio>
#include<cstring>
using namespace std;
const int maxs=1e7+10;
const int maxp=1e5+10;
int next[maxp];
char s[maxs],p[maxp];
void get_next(int len)
{
next[0]=-1;
int j=-1;
int i=0;
while(i<len){
if(j==-1||p[j]==p[i])
next[++i]=++j;
else
j=next[j];
}
return ;
}
int kmp(int slen,int plen)
{
get_next(plen);
int cnt=0;
int i=0,j=0;
while(i<slen){
if(j==-1||s[i]==p[j])
i++,j++;
else
j=next[j];
if(j==plen){
cnt++;
j=next[j];
}
}
return cnt;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%s%s",p,s);
printf("%d\n",kmp(strlen(s),strlen(p)));
}
return 0;
}
数组区间构建修改与查询-线段树
#include<iostream>
#include<cstdio>
#define L(t) t<<1
#define R(t) t<<1|1
using namespace std;
const int maxn=1e5+10;
struct Tree
{
int l,r,val,add;
}tree[maxn<<2];
void build(int l,int r,int t)
{
tree[t].l=l;
tree[t].r=r;
tree[t].add=0;
if(l==r){
tree[t].val=1;
return ;
}
int mid=(l+r)>>1;
build(l,mid,L(t));
build(mid+1,r,R(t));
tree[t].val=tree[L(t)].val+tree[R(t)].val;
}
void pushdown(int t)
{
if(tree[t].add){
tree[L(t)].add=tree[R(t)].add=tree[t].add;
tree[L(t)].val=tree[t].add*(tree[L(t)].r-tree[L(t)].l+1);
tree[R(t)].val=tree[t].add*(tree[R(t)].r-tree[R(t)].l+1);
tree[t].add=0;
}
}
void update(int l,int r,int val,int t)
{
if(tree[t].l>=l&&tree[t].r<=r){
tree[t].add=val;
tree[t].val=val*(tree[t].r-tree[t].l+1);
return ;
}
pushdown(t);
if(l<=tree[L(t)].r)
update(l,r,val,L(t));
if(r>=tree[R(t)].l)
update(l,r,val,R(t));
tree[t].val=tree[L(t)].val+tree[R(t)].val;
}
int query(int l,int r,int t)
{
if(tree[t].l>=l&&tree[t].r<=r){
return tree[t].val;
}
pushdown(t);
int a=0,b=0;
if(l<=tree[L(t)].r)
a=query(l,r,L(t));
if(r>=tree[R(t)].l)
b=query(l,r,R(t));
tree[t].val=tree[L(t)].val+tree[R(t)].val;
return a+b;
}
int main()
{
int c,n,t;
int x,y,z,k=0;
scanf("%d",&c);
while(c--){
scanf("%d",&n);
build(1,n,1);
scanf("%d",&t);
while(t--){
scanf("%d%d%d",&x,&y,&z);
update(x,y,z,1);
}
printf("Case %d: The total value of the hook is %d.\n",++k,query(1,n,1));
}
return 0;
}
区间修改单值查询-树状数组
#include<cstdio>
#include<cstring>
#define lowbit(x) (x&(-x))
using namespace std;
const int MAXN=1e5+10;
int tree[MAXN];
int n;
void add(int x,int val)
{
while(x<=n){
tree[x]+=val;
x+=lowbit(x);
}
}
int query(int x)
{
int sum=0;
while(x){
sum+=tree[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
while(scanf("%d",&n)!=EOF,n){
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++){
int a,b;
scanf("%d%d",&a,&b);
add(a,1);
add(b+1,-1);
}
for(int i=1;i<=n;i++){
if(i>1) printf(" ");
printf("%d",query(i));
}
printf("\n");
}
return 0;
}