zoukankan      html  css  js  c++  java
  • 蓝书4.1-4.4 树状数组、RMQ问题、线段树、倍增求LCA

    这章的数据结构题很真实

    T1 排队 bzoj 1699

    题目大意:

    求静态一些区间的最大值-最小值

    思路:

    ST表裸题

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #define ll long long
    10 #define inf 2139062143
    11 #define MAXN 100100
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 int n,q,g[MAXN],mn[MAXN][20],mx[MAXN][20];
    21 int main()
    22 {
    23     n=read(),q=read();int a,b,t;
    24     for(int i=1;i<=n;i++) mn[i][0]=mx[i][0]=g[i]=read();
    25     for(int j=1;j<20;j++)
    26         for(int i=1;i+(1<<j)-1<=n;i++)
    27             mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]),mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
    28     while(q--)
    29     {
    30         a=read(),b=read(),t=b-a+1,t=(int)log2(t);
    31         printf("%d
    ",max(mx[a][t],mx[b-(1<<t)+1][t])-min(mn[a][t],mn[b-(1<<t)+1][t]));
    32     }
    33 }
    View Code

    T2 选择客栈 luogu 1311

    题目大意:

    每个点有两个值 颜色和最小消费值 如果两个点对之间存在一个点最小消费值<=n

    求这样的点对的个数

    思路:

    把每个颜色分别用链表存起来 记录上一个<=p的位置

    对于每个颜色分别遍历

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #define ll long long
    10 #define inf 2139062143
    11 #define MAXN 200100
    12 using namespace std;
    13 inline int read()
    14 {
    15     int x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 int n,k,p,g[MAXN],c[MAXN],tmp[60],fst[60],las,cnt,res,ans,l[MAXN],to[MAXN];
    21 int main()
    22 {
    23     n=read(),k=read(),p=read();
    24     for(int i=1;i<=n;i++)
    25     {
    26         c[i]=read(),g[i]=read();
    27         if(g[i]<=p) las=i;l[i]=las;
    28         if(!tmp[c[i]]) fst[c[i]]=i,tmp[c[i]]=i;
    29         else to[tmp[c[i]]]=i,tmp[c[i]]=i;
    30     }
    31     for(int i=0,pos;i<k;i++)
    32     {
    33         pos=fst[i],cnt=1,res=0;
    34         while(to[pos])
    35         {
    36             if(to[pos]>n) break;
    37             if(l[to[pos]]>=pos) res=cnt;
    38             ans+=res,cnt++,pos=to[pos];
    39         }
    40     }
    41     printf("%d",ans);
    42 }
    View Code

    T3 最大值  bzoj 1012

    题解链接

    T4 花神游历各国 bzoj 3211

    题解链接

    T5 维护序列 bzoj 1798

    题目大意:

    区间乘法和加法以及区间求和

    思路:

    维护两个tag 所有地方注意先乘后加

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<cmath>
     6 #include<algorithm>
     7 #include<queue>
     8 #include<vector>
     9 #define ll long long
    10 #define inf 2139062143
    11 #define MAXN 100100
    12 using namespace std;
    13 inline ll read()
    14 {
    15     ll x=0,f=1;char ch=getchar();
    16     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    17     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
    18     return x*f;
    19 }
    20 ll n,MOD,tp[MAXN<<2],tm[MAXN<<2],sum[MAXN<<2];
    21 void build(int k,int l,int r)
    22 {
    23     tm[k]=1;
    24     if(l==r) {return ;}
    25     int mid=(l+r)>>1;
    26     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
    27 }
    28 inline void pshd(int k,int l,int mid,int r)
    29 {
    30     (sum[k<<1]*=tm[k])%=MOD,(sum[k<<1|1]*=tm[k])%=MOD;
    31     (tp[k<<1]*=tm[k])%=MOD,(tp[k<<1|1]*=tm[k])%=MOD;
    32     (tm[k<<1]*=tm[k])%=MOD,(tm[k<<1|1]*=tm[k])%=MOD,tm[k]=1;
    33     (sum[k<<1]+=tp[k]*(mid-l+1)%MOD)%=MOD,(sum[k<<1|1]+=tp[k]*(r-mid)%MOD)%=MOD;
    34     (tp[k<<1]+=tp[k])%=MOD,(tp[k<<1|1]+=tp[k])%=MOD,tp[k]=0;
    35 }
    36 inline void mdfm(int k,int l,int r,int a,int b,ll x)
    37 {
    38     if(l==a&&r==b){(sum[k]*=x)%=MOD,(tp[k]*=x)%=MOD,(tm[k]*=x)%=MOD;return ;}
    39     int mid=(l+r)>>1;
    40     pshd(k,l,mid,r);
    41     if(mid>=b) mdfm(k<<1,l,mid,a,b,x);
    42     else if(mid<a) mdfm(k<<1|1,mid+1,r,a,b,x);
    43     else {mdfm(k<<1,l,mid,a,mid,x);mdfm(k<<1|1,mid+1,r,mid+1,b,x);}
    44     sum[k]=(sum[k<<1]+sum[k<<1|1])%MOD;
    45 }
    46 inline void mdfp(int k,int l,int r,int a,int b,ll x)
    47 {
    48     if(l==a&&r==b) {(sum[k]+=x*(r-l+1)%MOD)%=MOD,tp[k]+=x;return ;}
    49     int mid=(l+r)>>1;
    50     pshd(k,l,mid,r);
    51     if(mid>=b) mdfp(k<<1,l,mid,a,b,x);
    52     else if(mid<a) mdfp(k<<1|1,mid+1,r,a,b,x);
    53     else {mdfp(k<<1,l,mid,a,mid,x);mdfp(k<<1|1,mid+1,r,mid+1,b,x);}
    54     sum[k]=(sum[k<<1]+sum[k<<1|1])%MOD;
    55 }
    56 inline ll query(int k,int l,int r,int a,int b)
    57 {
    58     if(l==a&&r==b) return sum[k];
    59     int mid=(l+r)>>1;
    60     pshd(k,l,mid,r);
    61     if(mid>=b) return query(k<<1,l,mid,a,b);
    62     else if(mid<a) return query(k<<1|1,mid+1,r,a,b);
    63     else return (query(k<<1,l,mid,a,mid)+query(k<<1|1,mid+1,r,mid+1,b))%MOD;
    64 }
    65 int main()
    66 {
    67     n=read(),MOD=read();int a,b,c;build(1,1,n);
    68     for(int i=1;i<=n;i++) mdfp(1,1,n,i,i,read());
    69     int T=read();
    70     while(T--)
    71     {
    72         a=read();
    73         if(a==1) {a=read(),b=read(),c=read();mdfm(1,1,n,a,b,c);}
    74         else if(a==2) {a=read(),b=read(),c=read();mdfp(1,1,n,a,b,c);}
    75         else if(a==3) {a=read(),b=read();printf("%lld
    ",query(1,1,n,a,b));}
    76     }
    77 }
    View Code
  • 相关阅读:
    Linux设备模型 学习总结
    平衡二叉树
    数字在排序数组中出现的次数
    两个链表的第一个公共节点
    第一个只出现一次的字符
    丑数
    把数组排成最小的数
    剑指offer 连续子数组的最大和
    查找描述信息中包括robot的电影对应的分类名称以及电影数目,而且还需要该分类对应电影数量>=5部
    for each
  • 原文地址:https://www.cnblogs.com/yyc-jack-0920/p/9429765.html
Copyright © 2011-2022 走看看