zoukankan      html  css  js  c++  java
  • GZOI 2017配对统计 树状数组

    题目

    https://www.luogu.com.cn/problem/P5677

    分析

      最开始读题的时候没有读的太懂,以为i是在选定区间内给的,实际上不是,这道题的意思应该是在l和r的区间内找出有多少个好的配对,这里好的配对是对于整个区间来说的,既然是对于整个区间,我们就不难想到找出好的配对的方法,所以我们可以先找出所有好的配对,然后用树状数组维护个数。

      如何找出好的配对呢?我们先来分析什么叫好的配对,选定的两点间距离比其中一点到除对方外任意一点的距离都小,也就是说这两点差的绝对值最小,这样的话,这两个点在sort排序后一定相邻,这个很好推出,于是我们只要考虑这个点的另一个配对是左边的点还是右边的点,写一个判断就行了,注意特判1和n。

      找出好的配对来,就又向答案接近了一步,现在我们只要进行更新就行了,这里的更新我们枚举左端点,上一步我们已经求出了好的配对(l,r)如果查询的左端点在l的左边,那么从r开始向右就一定至少存在一个好的配对,所以让树状数组中的r对应的位置更新就行。注意我们要倒序枚举左端点,因为我们加入r后所产生的配对只能是在询问区间包含l的情况下才有效。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<vector>
     5 using namespace std;
     6 const int N=3e5+10;
     7 #define ll long long
     8 struct Node{
     9     ll val,id;
    10     bool operator < (const Node&A)const{
    11         return val<A.val;
    12     }
    13 }a[N];
    14 vector<int> point[N],p1[N],p2[N];
    15 ll lowbit(ll x){
    16     return x&-x;
    17 }
    18 void Ins(ll x,ll y){
    19     point[min(x,y)].push_back(max(x,y));//min表示左端点,max表示右端点
    20 }
    21 ll m,n,c[N];
    22 void Add(ll x){
    23     while(x<=n){
    24         c[x]++;
    25         x+=lowbit(x);
    26     }
    27 }
    28 ll query(ll x){
    29     ll ans=0;
    30     while(x){
    31         ans+=c[x];
    32         x-=lowbit(x);
    33     }
    34     return ans;
    35 }
    36 ll ans[N];
    37 int main(){
    38     scanf("%lld%lld",&n,&m);
    39     for(int i=1;i<=n;i++){
    40         scanf("%lld",&a[i].val);a[i].id=i;
    41     }
    42     sort(a+1,a+n+1);
    43     for(int i=1;i<=n;i++){
    44         int Min=0x3f3f3f3f;
    45         if(i!=1&&a[i].val-a[i-1].val<Min){
    46             Min=a[i].val-a[i-1].val;
    47         }
    48         if(i!=n&&a[i+1].val-a[i].val<Min){
    49             Min=a[i+1].val-a[i].val;
    50         }
    51         if(i!=1&&a[i].val-a[i-1].val==Min)Ins(a[i].id,a[i-1].id);
    52         if(i!=n&&a[i+1].val-a[i].val==Min)Ins(a[i+1].id,a[i].id);//取两个端点最小值
    53     }
    54     for(int i=1;i<=m;i++){
    55         int l,r;
    56         scanf("%d%d",&l,&r);
    57         p1[l].push_back(r);
    58         p2[l].push_back(i);//记录坐标位置
    59     }
    60     for(int i=n;i>=1;i--){
    61         for(int j=0;j<(int)point[i].size();j++)Add(point[i][j]);//倒序查询
    62         for(int j=0;j<(int)p1[i].size();j++)ans[p2[i][j]]=query(p1[i][j]);
    63     }
    64     ll sum=0;
    65     for(int i=1;i<=m;i++)
    66         sum+=ans[i]*i;
    67     printf("%lld
    ",sum);
    68 }
  • 相关阅读:
    什么是webview
    juqery.fn.extend和jquery.extend
    LeetCode
    5. Longest Palindromic Substring
    42. Trapping Rain Water
    11. Container With Most Water
    621. Task Scheduler
    49. Group Anagrams
    739. Daily Temperatures
    3. Longest Substring Without Repeating Characters
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12461717.html
Copyright © 2011-2022 走看看