【模板】数据结构

线段树:

#include<iostream>
#define MAXN 101000
#define LL long long
using namespace std;
struct nond{
    LL l,r,dis,flag;    
}tree[MAXN*4];
int N,M,a,b,c,Z;
void tree_up(LL now){
    tree[now].dis=tree[now*2].dis+tree[now*2+1].dis;
}
void tree_build(LL now,LL l,LL r){
    tree[now].l=l;
    tree[now].r=r;
    if(l==r){
        cin>>tree[now].dis;
        return;
    }
    LL mid=(tree[now].l+tree[now].r)/2;
    tree_build(now*2,l,mid);
    tree_build(now*2+1,mid+1,r);
    tree_up(now);
}
void tree_down(LL now){
    tree[now*2].flag+=tree[now].flag;
    tree[now*2+1].flag+=tree[now].flag;
    tree[now*2].dis+=tree[now].flag*(tree[now*2].r-tree[now*2].l+1);
    tree[now*2+1].dis+=tree[now].flag*(tree[now*2+1].r-tree[now*2+1].l+1);
    tree[now].flag=0;
    return ;
}
void tree_change_many(LL now,LL l,LL r,LL x){
    if(tree[now].l==l&&tree[now].r==r){
        tree[now].dis+=x*(tree[now].r-tree[now].l+1);
        tree[now].flag+=x;
        return ;
    }
    if(tree[now].flag)    tree_down(now);
    LL mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    tree_change_many(now*2,l,r,x);
    else if(l>mid)    tree_change_many(now*2+1,l,r,x);
    else{
        tree_change_many(now*2,l,mid,x);
        tree_change_many(now*2+1,mid+1,r,x);
    }
    tree_up(now);
}
LL tree_query_many(LL now,LL l,LL r){
    if(tree[now].l==l&&tree[now].r==r){
        return tree[now].dis;
    }
    if(tree[now].flag)    tree_down(now);
    LL mid=(tree[now].l+tree[now].r)/2;
    if(r<=mid)    return tree_query_many(now*2,l,r);
    else if(l>mid)    return tree_query_many(now*2+1,l,r);
    else    return tree_query_many(now*2,l,mid)+tree_query_many(now*2+1,mid+1,r);
}
int main(){
    cin>>N>>M;
    tree_build(1,1,N);
    for(LL i=1;i<=M;i++){
        cin>>Z;
        if(Z==1){
            cin>>a>>b>>c;
            tree_change_many(1,a,b,c);
        }
        else if(Z==2){
            cin>>a>>b;
            cout<<tree_query_many(1,a,b)<<endl;
        }
    }
    return 0;
}
区间修改区间查询
#include<cstdio>
using namespace std;
int n,p,a,b,m,x,ans;
struct node
{
    int l,r,w,f;
}tree[400001];
inline void build(int k,int ll,int rr)
{
    tree[k].l=ll,tree[k].r=rr;
    if(tree[k].l==tree[k].r)
    {
        scanf("%d",&tree[k].w);
        return;
    }
    int m=(ll+rr)/2;
    build(k*2,ll,m);
    build(k*2+1,m+1,rr);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
inline void down(int k)
{
    tree[k*2].f+=tree[k].f;
    tree[k*2+1].f+=tree[k].f;
    tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
    tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
    tree[k].f=0;
}
inline void add(int k)
{
    if(tree[k].l>=a&&tree[k].r<=b)
    {
        tree[k].w+=(tree[k].r-tree[k].l+1)*x;
        tree[k].f+=x;
        return;
    }
    if(tree[k].f) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(a<=m) add(k*2);
    if(b>m) add(k*2+1);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
inline void ask(int k)
{
    if(tree[k].l==tree[k].r)
    {
        ans=tree[k].w;
        return;
    }
    if(tree[k].f) down(k);
    int m=(tree[k].l+tree[k].r)/2;
    if(x<=m) ask(k*2);
    else ask(k*2+1); 
}
int main()
{
    scanf("%d",&n);
    build(1,1,n);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d",&p);
        if(p==1)
        {
            scanf("%d%d%d",&a,&b,&x);
            add(1);
        }
        else
        {
            scanf("%d",&x);
            ask(1);
            printf("%d\n",ans);
        }
    }
}
单点查询区间修改
#include<cstdio>
using namespace std;
int n,m,p,x,y,ans;
struct node
{
    int l,r,w;
}tree[400001];
inline void build(int l,int r,int k)
{
    tree[k].l=l;tree[k].r=r;
    if(l==r) 
    {
        scanf("%d",&tree[k].w);
        return ;
    }
    int m=(l+r)/2;
    build(l,m,k*2);
    build(m+1,r,k*2+1);
    tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
inline void add(int k)
{
    if(tree[k].l==tree[k].r)
    {
        tree[k].w+=y;
        return;
    }
    int m=(tree[k].l+tree[k].r)/2;
    if(x<=m) add(k*2);
    else add(k*2+1);
    tree[k].w=tree[k*2].w+tree[k*2+1].w; 
}
inline void sum(int k)
{
    if(tree[k].l>=x&&tree[k].r<=y) 
    {
        ans+=tree[k].w;
        return;
    }
    int m=(tree[k].l+tree[k].r)/2;
    if(x<=m) sum(k*2);
    if(y>m) sum(k*2+1);
}
int main()
{
    scanf("%d",&n);
    build(1,n,1);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&p,&x,&y);
        ans=0;
        if(p==1) add(1);
        else 
        {
            sum(1);
            printf("%d\n",ans);
        }
    }
}
单点查询取件修改
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define MAXN 100010
using namespace std;
LL l[MAXN<<2],r[MAXN<<2],dis[MAXN<<2],falg1[MAXN<<2],falg2[MAXN<<2];
LL n,m,p;
void up(LL now){
    dis[now]=(dis[now<<1]+dis[now<<1|1])%p;
}
void build(LL now,LL ll,LL rr){
    l[now]=ll;
    r[now]=rr;
    if(l[now]==r[now]){
        cin>>dis[now];
        return;
    }
    LL mid=(l[now]+r[now])>>1;
    build(now<<1,ll,mid);
    build(now<<1|1,mid+1,rr);
    up(now);
}
void down(LL now){
    if(falg1[now]!=1){
        falg2[now<<1]=falg2[now<<1]*falg1[now]%p;
        falg2[now<<1|1]=falg2[now<<1|1]*falg1[now]%p;
        dis[now<<1]=falg1[now]*dis[now<<1]%p;
        dis[now<<1|1]=falg1[now]*dis[now<<1|1]%p;
        falg1[now<<1]=falg1[now<<1]*falg1[now]%p;
        falg1[now<<1|1]=falg1[now<<1|1]*falg1[now]%p;
        falg1[now]=1;
    }
    if(falg2[now]){
        dis[now<<1]=(dis[now<<1]+falg2[now]*(r[now<<1]-l[now<<1]+1)%p)%p;
        dis[now<<1|1]=(dis[now<<1|1]+falg2[now]*(r[now<<1|1]-l[now<<1|1]+1)%p);
        falg2[now<<1]=(falg2[now<<1]+falg2[now])%p;
        falg2[now<<1|1]=(falg2[now<<1|1]+falg2[now])%p;
        falg2[now]=0;
    }
}
void changec(LL now,LL ll,LL rr,LL k){
    if(l[now]==ll&&r[now]==rr){
        dis[now]=dis[now]*k%p;
        falg1[now]=falg1[now]*k%p;
        falg2[now]=falg2[now]*k%p;
        return;
    }
    if(falg1[now]!=0||falg2[now])    down(now);
    LL mid=(l[now]+r[now])>>1;
    if(rr<=mid)    changec(now<<1,ll,rr,k);
    else if(ll>mid)    changec(now<<1|1,ll,rr,k);
    else{
        changec(now<<1,ll,mid,k);
        changec(now<<1|1,mid+1,rr,k);
    }    
    up(now);
}
void changej(LL now,LL ll,LL rr,LL k){
    if(l[now]==ll&&r[now]==rr){
        dis[now]=(dis[now]+k*(r[now]-l[now]+1)%p)%p;
        falg2[now]+=k;
        return;
    }
    if(falg1[now]!=1||falg2[now])    down(now);
    LL mid=(l[now]+r[now])>>1;
    if(rr<=mid)    changej(now<<1,ll,rr,k);
    else if(ll>mid)    changej(now<<1|1,ll,rr,k);
    else{
        changej(now<<1,ll,mid,k);
        changej(now<<1|1,mid+1,rr,k);
    }    
    up(now);
}
LL query(LL now,LL ll,LL rr){
    if(l[now]==ll&&r[now]==rr)
        return dis[now]%p;
    if(falg1[now]!=1||falg2[now])    down(now);
    LL mid=(l[now]+r[now])>>1;
    if(rr<=mid)    return query(now<<1,ll,rr);
    else if(ll>mid)    return query(now<<1|1,ll,rr);
    else    return query(now<<1|1,mid+1,rr)+query(now<<1,ll,mid);
}
int main(){
    cin>>n>>m>>p;
    build(1,1,n);
    memset(falg2,0,sizeof(falg2));
    for(LL i=1;i<=n*4;i++)
        falg1[i]=1;
    for(LL i=1;i<=m;i++){
        LL z,x,y,k;
        cin>>z>>x>>y;
        if(z==1){
            cin>>k;
            changec(1,x,y,k);
        } else if(z==2){
            cin>>k;
            changej(1,x,y,k);
        } else
            cout<<query(1,x,y)%p<<endl;
    }
}
带有加法和乘法的线段树

trie树

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 500010
using namespace std;
char s[50];
int n,m,tot,len,root;
int sum[MAXN],tree[MAXN][30];
void insert(){
    root=0;
    len=strlen(s);
    for(int i=0;i<len;i++){
        int x=s[i]-'a';
        if(!tree[root][x])
            tree[root][x]=++tot;
        root=tree[root][x]; 
    }
    sum[root]=1;
}
void find(){
    root=0;
    len=strlen(s);
    for(int i=0;i<len;i++){
        int x=s[i]-'a';
        if(!tree[root][x]){
            cout<<"WRONG"<<endl;
            return ;
        }
        root=tree[root][x];
    }
    if(sum[root]==1){
        sum[root]++;
        cout<<"OK"<<endl;
        return ;
    }
    else{
        cout<<"REPEAT"<<endl;
        return ;
    }
}
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%s",s);
        insert();
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%s",s);
        find();    
    }
}
查询某个字符串是否出现过
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int trie[400001][26],len,root,tot,sum[400001];
bool p;
int n,m; 
char s[11];
void insert()
{
    len=strlen(s);
    root=0;
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';
        if(!trie[root][id]) trie[root][id]=++tot;
        sum[trie[root][id]]++;//前缀后移一个位置保存 
        root=trie[root][id];
    }
}
int search()
{
    root=0;
    len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int id=s[i]-'a';
        if(!trie[root][id]) return 0;
        root=trie[root][id];
    }//root经过此循环后变成前缀最后一个字母所在位置的后一个位置 
    return sum[root];//因为前缀后移了一个保存,所以此时的sum[root]就是要求的前缀出现的次数 
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>s;
        insert();
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        cin>s;
        printf("%d\n",search());
    }
}
查询某个档次的出现次数

...

posted @ 2017-11-07 20:49  一蓑烟雨任生平  阅读(250)  评论(0编辑  收藏  举报