• 51nod 1463 找朋友(线段树+离线处理)


    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1463

    题意:

    思路:

    好题!

    先对所有查询进行离线处理,按照右区间排序,因为k一共最多只有10个,所有在该区间内的B数组,每次枚举K值,通过这样的方式来得到另外一个B值。但是这样得到的B值它在B数组中的位置必须在当前数的左边。如下图:(j为当前数在B数组中的位置,pos为计算得到的另一个B值在数组中的位置)

    这两个数的和记录在pos中,这里pos的位置必须在j的左边,假设第q个查询区间如上图所示(请在脑中将pos和j互换一下),那么此时j就没包含在该区间内,这样一来,查询得到的值就会有错。因为我们是按照右区间排序的,所以右区间会不断扩大,只要左边被覆盖的,那么右边的数肯定是在该区间内的。

    用线段树维护即可。具体请参见代码。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 const int INF = 0x3f3f3f3f;
     14 const int maxn=1e5+5;
     15 
     16 int n,q,m;
     17 int A[maxn],B[maxn],K[15],B_pos[maxn],ans[maxn];
     18 
     19 struct node
     20 {
     21     int l,r,id;
     22     bool operator<(const node& rhs) const
     23     {
     24         return r<rhs.r;
     25     }
     26 }Q[maxn];
     27 
     28 int MAX[maxn<<2];
     29 int val[maxn<<2];
     30 
     31 void build(int l, int r, int o)
     32 {
     33     val[o]=0;
     34     if(l==r)  return;
     35     int mid=(l+r)>>1;
     36     build(l,mid,o<<1);
     37     build(mid+1,r,o<<1|1);
     38 }
     39 
     40 void update(int l, int r, int pos, int x, int o)
     41 {
     42     val[o]=max(val[o],x);
     43     if(l==pos && r==pos)  return;
     44     int mid=(l+r)>>1;
     45     if(pos<=mid)  update(l,mid,pos,x,o<<1);
     46     else   update(mid+1,r,pos,x,o<<1|1);
     47 }
     48 
     49 int query(int ql, int qr, int l, int r, int o)
     50 {
     51     if(ql<=l && qr>=r)  return val[o];
     52     int mid=(l+r)>>1;
     53     int res=0;
     54     if(ql<=mid)  res=max(res,query(ql,qr,l,mid,o<<1));
     55     if(qr>mid)   res=max(res,query(ql,qr,mid+1,r,o<<1|1));
     56     return res;
     57 }
     58 
     59 int main()
     60 {
     61    //freopen("in.txt","r",stdin);
     62     scanf("%d%d%d",&n,&q,&m);
     63     for(int i=1;i<=n;i++)  scanf("%d",&A[i]);
     64     for(int i=1;i<=n;i++)  {scanf("%d",&B[i]);B_pos[B[i]]=i;}
     65     for(int i=1;i<=m;i++)  scanf("%d",&K[i]);
     66     for(int i=1;i<=q;i++)
     67     {
     68         scanf("%d%d",&Q[i].l,&Q[i].r);
     69         Q[i].id=i;
     70     }
     71     sort(Q+1,Q+q+1);
     72     build(1,n,1);
     73     int s=1;
     74     memset(MAX,0,sizeof(MAX));
     75     for(int i=1;i<=q;i++)
     76     {
     77         int r=Q[i].r;
     78         for(int j=s;j<=r;j++)
     79         {
     80             for(int k=1;k<=m;k++)
     81             {
     82                 int tmp_B=B[j]+K[k];
     83                 int pos=B_pos[tmp_B];  //得到tmp_B在B数组中的位置
     84                 if(tmp_B<=n && pos<j && A[pos]+A[j]>MAX[pos])
     85                 {
     86                     MAX[pos]=A[pos]+A[j];  //此时pos位置的最大值是由pos和[1,j)之间的一个数相加而成
     87                     update(1,n,pos,MAX[pos],1); //更新线段树
     88                 }
     89                 tmp_B=B[j]-K[k];
     90                 pos=B_pos[tmp_B];
     91                 if(tmp_B>=1 && pos<j && A[pos]+A[j]>MAX[pos])
     92                 {
     93                     MAX[pos]=A[pos]+A[j];
     94                     update(1,n,pos,MAX[pos],1);
     95                 }
     96             }
     97         }
     98         ans[Q[i].id]=query(Q[i].l,Q[i].r,1,n,1); //查询该区间内的最大值
     99         s=r;
    100     }
    101     for(int i=1;i<=q;i++)  printf("%d
    ",ans[i]);
    102     return 0;
    103 }

    再给一个树状数组的吧,按照左区间从大到小排序。

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<cstdio>
     5 #include<vector>
     6 #include<stack>
     7 #include<queue>
     8 #include<cmath>
     9 #include<map>
    10 #include<set>
    11 using namespace std;
    12 typedef long long ll;
    13 const int INF = 0x3f3f3f3f;
    14 const int maxn=1e5+5;
    15 
    16 int n,q,m;
    17 int A[maxn],B[maxn],K[15],B_pos[maxn],ans[maxn],c[maxn];
    18 
    19 struct node
    20 {
    21     int l,r,id;
    22     bool operator<(const node& rhs) const
    23     {
    24         return l>rhs.l;
    25     }
    26 }Q[maxn];
    27 
    28 int lowbit(int x)
    29 {
    30     return x&(-x);
    31 }
    32 
    33 int find_max(int x)
    34 {
    35     int res=0;
    36     while(x>0)
    37     {
    38         res=max(res,c[x]);
    39         x-=lowbit(x);
    40     }
    41     return res;
    42 }
    43 
    44 void update(int x, int val)
    45 {
    46     while(x<=n)
    47     {
    48         c[x]=max(c[x],val);
    49         x+=lowbit(x);
    50     }
    51 }
    52 
    53 int main()
    54 {
    55     //freopen("in.txt","r",stdin);
    56     scanf("%d%d%d",&n,&q,&m);
    57     for(int i=1;i<=n;i++)  scanf("%d",&A[i]);
    58     for(int i=1;i<=n;i++)  {scanf("%d",&B[i]);B_pos[B[i]]=i;}
    59     for(int i=1;i<=m;i++)  scanf("%d",&K[i]);
    60     for(int i=1;i<=q;i++)
    61     {
    62         scanf("%d%d",&Q[i].l,&Q[i].r);
    63         Q[i].id=i;
    64     }
    65     sort(Q+1,Q+q+1);
    66     memset(c,0,sizeof(c));
    67     int s=n+1;
    68     for(int i=1;i<=q;i++)
    69     {
    70         for(int j=s-1;j>=Q[i].l;j--)
    71         {
    72             for(int k=1;k<=m;k++)
    73             {
    74                 int tmp_B=B[j]+K[k];
    75                 int pos=B_pos[tmp_B];
    76                 if(tmp_B<=n && pos>j)
    77                 {
    78                     update(pos,A[pos]+A[j]);
    79                 }
    80                 tmp_B=B[j]-K[k];
    81                 pos=B_pos[tmp_B];
    82                 if(tmp_B>=1 && pos>j)
    83                 {
    84                     update(pos,A[pos]+A[j]);
    85                 }
    86             }
    87         }
    88         s=Q[i].l;
    89         ans[Q[i].id]=find_max(Q[i].r);
    90     }
    91 
    92     for(int i=1;i<=q;i++)  printf("%d
    ",ans[i]);
    93     return 0;
    94 }
  • 相关阅读:
    SlideShowExtender制作相册
    Response.Redirect(),Server.Transfer(),Server.Execute()的区别
    虚方法,抽象类,多态性
    gridview获取当前行索引的方法
    AutoQueryTextBox(AjaxPro.dll)非常值得研究的javascript代码
    abstract & virtual & override & new比较(转)
    Asp.net技巧:gridview获取当前行索引的方法
    js 获取浏览器高度和宽度值
    深入理解abstract class和interface
    c++ 静态数据成员和静态成员函数
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7429661.html
Copyright © 2020-2023  润新知