zoukankan      html  css  js  c++  java
  • [51nod] 1463 找朋友 #离线+扫描线

    1463 找朋友

    基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80 难度:5级算法题
     
    给定:
    两个长度为n的数列A 、B
    一个有m个元素的集合K
    询问Q次
    每次询问[l,r],输出区间内满足|Bi-Bj|∈K 的最大Ai+Aj
     
    数据约定:
    n,Q<=100000
    m <= 10
    0<=A[i]<=1000000000
    1<=B[i]<=n
    1<=K[i]<=n
    保证B[i]互不相等
    Input
    n Q m
    A1 A2 ....An
    B1 B2 ....Bn
    K1 K2 ....Km
    l1 r1
    l2 r2
    .
    .
    lQ rQ
    Output
    Q行,每行一个整数表示相对应的答案。
    如果找不到这样的两个数则输出0。
    Input示例
    4 2 2
    1 2 3 4
    3 2 1 4
    1 3
    1 4
    2 3
    Output示例
    7
    5
    Analysis分析
    正解:扫描线 + 离线
    首先将询问区间按右端点进行升序排序
    然后从 1 扫到 n 扫过每一个元素
    假定当前元素为 i 
    枚举 K 集合,找出所有在 i 左边的并且与 i 满足条件的另一个元素 j
    (我们可以通过 K 和 i 逆推出 j 的 Bi 即排名,然后各种简单操作可以找到 j 的编号位置)
    然后将这两个元素的和储存在 j 中(当然是取最大值更新啦)
    那么这么干有一个缺点:如果 i 右边有另一个更优的元素,那么储存在 j 中的答案会被更新,不一定可以满足某些询问区间
    所以随扫随答,如果当前这个 i 挂着询问(我把询问直接用链表在右端点上qwq),那么当即查询 [ Li,Ri ] 的答案的最大值(这里可用数据结构如线段树优化)
    如此这般便不会被后面的元素影响了

    所以我还学到一件事情,如果有区间相关的话,试图排序并逐步扩大统计范围以确定当前答案为可行解
     
    Code代码
     1 #include<stdio.h>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define mid (L+R)/2
     5 #define lc (rt << 1)
     6 #define rc (rt<<1|1)
     7 #define maxn 1000000
     8 using namespace std;
     9 
    10 int arr[maxn],brr[maxn],cnt,bos[maxn],sto[maxn],k[maxn],n,m,q;
    11 
    12 struct node{
    13     int maxx;
    14 }T[maxn*4];
    15 
    16 void build(int rt,int L,int R){
    17     if(L == R) T[rt].maxx = arr[L];
    18     else{
    19         build(lc,L,mid); build(rc,mid+1,R);
    20         T[rt].maxx = max(T[lc].maxx,T[rc].maxx);
    21     }
    22 }
    23 
    24 void modify(int rt,int L,int R,int pos,int val){
    25     if(L == R) T[rt].maxx = val,sto[pos] = val;
    26     else{
    27         if(pos > R || pos < 1) return;
    28         if(pos <= mid) modify(lc,L,mid,pos,val);
    29         else modify(rc,mid+1,R,pos,val);
    30         T[rt].maxx = max(T[lc].maxx,T[rc].maxx);
    31     }
    32 }
    33 
    34 int query(int rt,int L,int R,int qL,int qR){
    35     if(qL <= L && R <= qR) return T[rt].maxx;
    36     else{
    37         int ans = 0;
    38         if(qL <= mid) ans = max(ans,query(lc,L,mid,qL,qR));
    39         if(qR > mid) ans = max(ans,query(rc,mid+1,R,qL,qR));
    40         return ans;
    41     }
    42 }
    43 
    44 struct ask{
    45     int from,L,R,ans,ord; // first[R]
    46 }e[maxn];
    47 int tot,first[maxn];
    48 void insert(int L,int R,int ord){
    49     tot++;
    50     e[tot].ord = ord,
    51     e[tot].L = L,
    52     e[tot].R = R,
    53     e[tot].from = first[R];
    54     first[R] = tot;
    55 }
    56 
    57 bool cmp(const ask &A,const ask &B){ return A.ord < B.ord; }
    58 
    59 int main(){
    60     scanf("%d%d%d",&n,&q,&m);
    61     
    62     for(int i = 1;i <= n;i++) scanf("%d",&arr[i]);
    63     for(int i = 1;i <= n;i++) scanf("%d",&brr[i]),bos[brr[i]] = i;
    64     for(int i = 1;i <= m;i++) scanf("%d",&k[i]);
    65     
    66     for(int i = 1;i <= q;i++){
    67         int L,R;
    68         scanf("%d%d",&L,&R);
    69         insert(L,R,i);
    70     }
    71     
    72 //    printf("#bos: "); for(int i = 1;i <= n;i++) printf("%d ",bos[i]); cout << endl;
    73     
    74     for(int i = 2;i <= n;i++){
    75         for(int j = 1;j <= m;j++){
    76             int ppos = bos[brr[i]-k[j]]; //printf("~#%d: ppos %d i-k[j] %d
    ",brr[i],ppos,i-k[j]);
    77             if(ppos >= 1 && ppos < i && sto[ppos] < arr[ppos]+arr[i])
    78                 modify(1,1,n,ppos,arr[ppos]+arr[i]);
    79             ppos = bos[brr[i]+k[j]]; //printf("~#%d: ppos %d i-k[j] %d
    ",brr[i],ppos,i-k[j]);
    80             if(ppos >= 1 && ppos < i && sto[ppos] < arr[ppos]+arr[i])
    81                 modify(1,1,n,ppos,arr[ppos]+arr[i]);
    82         }for(int p = first[i];p;p = e[p].from){
    83             e[p].ans = query(1,1,n,e[p].L,e[p].R);
    84         }//printf("#%d: ",i); for(int j = 1;j <= n;j++) printf("%d ",sto[j]); cout << endl;
    85     }sort(e+1,e+1+tot,cmp);
    86     
    87     for(int i = 1;i <= tot;i++) printf("%d
    ",e[i].ans);
    88     
    89     return 0;
    90 }
    qwq注释代码多又多
  • 相关阅读:
    复杂报表的存储过程
    Jquery中使用setInterval和setTimeout
    Jquery EasyUi实战教程布局篇
    枚举enum
    myGeneration代码生成器
    带有分页的存储过程
    应用临时表的存储过程
    缓存类的写法
    HDU4706 Children's Day
    HDU4706 Children's Day
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7755265.html
Copyright © 2011-2022 走看看