基础算法模板

最近公共祖先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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值