数据结构板子

来源:互联网 发布:sql 多列分组求和汇总 编辑:程序博客网 时间:2024/06/06 16:37

priority_queue

RMQ(区间最值)

#include<iostream>#include<cstdio>#define MAXN 100005using namespace std;int n,m;long long a[MAXN],d[MAXN][18];inline int read (){    int n=0;    char ch=getchar();    while(ch<'0'||ch>'9') ch=getchar();    while(ch>='0'&&ch<='9')     {        n=n*10+ch-'0';        ch=getchar();    }    return n;}inline void RMQ_pre(){    for(int i=1;i<=n;i++)    {        d[i][0]=read();    }    for(int j=1;(1<<j)<=n;j++)//(1<<j)<=n     for(int i=1;i+(1<<j)-1<=n;i++)//i+(1<<j)-1<=n      d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);} inline int RMQ(int l,int r){    int k=0;    while((1<<k)<=r-l+1) k++;    k--;    return max(d[l][k],d[r-(1<<k)+1][k]);}int main(){  n=read();  m=read();  RMQ_pre();  for(int i=1;i<=m;i++)  {    int l=read(),r=read();    printf("%d\n",RMQ(l,r));  }  return 0;}

线段树

#include<iostream>#include<cstdio>#include<cstdlib>#include<cmath>#include<cstring>#include<algorithm>#define LL long longusing namespace std;struct cs{    LL ll,rr,vv;}T[824290];LL a[200005],v[824290];LL n,m,x,y,z,sum,N;void clean(LL x){    if(!v[x])return;    T[x].vv+=(T[x].rr-T[x].ll+1)*v[x];    if(T[x].ll!=T[x].rr)    {        v[x*2]+=v[x];        v[x*2+1]+=v[x];    }    v[x]=0;}{    T[num].ll=x;    T[num].rr=y;    if(x==y) T[num].vv=a[x],return;    maketree(x,(x+y)/2,num*2);    maketree((x+y)/2+1,y,num*2+1);    T[num].vv=T[num*2].vv+T[num*2+1].vv;}void inc(LL x,LL y,LL z,LL num) {    clean(num);    if(x<=T[num].ll&&T[num].rr<=y) v[num]+=z, return;    T[num].vv+=(min(y,T[num].rr)-max(x,T[num].ll)+1)*z;    if(T[num].ll==T[num].rr) return;    int mid=(T[num].ll+T[num].rr)/2;    if(x>mid)inc(x,y,z,num*2+1);    else      if(y<=mid)inc(x,y,z,num*2);else        {         inc(x,y,z,num*2);         inc(x,y,z,num*2+1);        }}void out(int LL,int LL,LL num){    clean(num);    if(x<=T[num].ll&&T[num].rr<=y) sum+=T[num].vv,return;    int mid=(T[num].ll+T[num].rr)/2;    if(x>mid)out(x,y,num*2+1);      else      if(y<=mid)out(x,y,num*2);        else        {         out(x,y,num*2);         out(x,y,num*2+1);        }}int main(){    scanf("%d%d",&n,&N);    for(int i=1;i<=n;i++)scanf("%d",&a[i]);    maketree(1,n,1);    for(int i=1;i<=N;i++)    {        scanf("%d%d%d",&m,&x,&y);        if(m==1)        {            scanf("%d",&z);            inc(x,y,z,1);        }        else        {            sum=0;            out(x,y,1);            printf("%lld\n",sum);//用cout输出什么事都没有         }    }}

树状数组

-比线段树短啊
1. 单点修改,区间查询(codevs1080 线段树练习)
单点修改:

#define lowbit(x) x&(~x+1)using namespace std;int a[MAXN],tree[MAXN],n,q;void add(int k,int x){    while(k <= n)    {        tree[k] += x;        k += lowbit(k);    }}

  区间查询:

int read(int k){    int sum = 0;    while(k)    {        sum += tree[k];        k -= lowbit(k);    }    return sum;}/*printf("%d\n",read(b) - read(a-1));//输出*/

2.区间修改,单点查询(codevs1081 线段树练习 2)
修改和查询函数与上面是一样的,不过预处理的时候有所不同,这里只放主函数代码

int main(){    scanf("%d",&n);    for(int i = 1; i <= n; i ++)    {        scanf("%d",&a[i]);        add(i,a[i]);        add(i+1,-a[i]);    }    scanf("%d",&q);    int t;    for(int i = 1; i <= q; i ++)    {        scanf("%d",&t);        if(t == 1)        {            int a,b,x;            scanf("%d%d%d",&a,&b,&x);            add(a,x);            add(b+1,-x);        }        if(t == 2)        {            int a;            scanf("%d",&a);            printf("%d\n",read(a));        }    }    return 0;}
  1. 区间修改,区间查询(codevs1082 线段树练习 3)
#include <cstdio>#include <algorithm>#include <cstring>#include <iostream>#define MAXN 200000+5#define lowbit(x) x&(~x+1)using namespace std;typedef long long ll;ll a[MAXN],d1[MAXN],d2[MAXN],n,q;void add(ll *d,ll k,ll x){    while(k <= n)    {        d[k] += x;        k += lowbit(k);    }}ll read(ll *d,ll k){    ll sum = 0;    while(k)    {        sum += d[k];        k -= lowbit(k);    }    return sum;}int main(){    scanf("%lld",&n);    for(int i = 1; i <= n; i ++)    {        scanf("%lld",&a[i]);        add(d1,i,a[i]);        add(d1,i+1,-a[i]);        add(d2,i,i*a[i]);        add(d2,i+1,-a[i]*(i+1));    }    scanf("%lld",&q);    int t;    for(int i = 1; i <= q; i ++)    {        scanf("%d",&t);        if(t == 1)        {            int a,b,x;            scanf("%d%d%d",&a,&b,&x);            add(d1,a,x);            add(d1,b+1,-x);            add(d2,a,x*a);            add(d2,b+1,-x*(b+1));        }        if(t == 2)        {            int a,b;            scanf("%d%d",&a,&b);            printf("%lld\n",((b+1)*read(d1,b)-read(d2,b))-(a*read(d1,a-1)-read(d2,a-1)));        }    }    return 0;}

并查集

#include<iostream>#include<cstdio>using namespace std;int x,y,n,m,q;int fa[20020];int find (int x){    if(fa[x]!=x) fa[x]=find(fa[x]);    return fa[x];}void unionn(int x,int y){   int r1=find(x),r2=find(y);   if(r1!=r2) fa[r2]=r1;    } int main(){    scanf("%d%d%d",&n,&m,&q);    for(int i=1;i<=n;i++)    {        fa[i]=i;    }    for(int i=1;i<=m;i++)    {        scanf("%d%d",&x,&y);        unionn(x,y);    }    for(int i=1;i<=q;i++)    {        scanf("%d%d",&x,&y);        if(find(x)==find(y)) printf("Yes\n");        else printf("No\n");    }    return 0;}

最小生成树

原创粉丝点击