• 【xsy1061】排列 树状数组


    题目大意:给你一个$1$到$n$的排列,问是否存在一对数$a,b(1≤a,b≤n,a≠b)$满足$a+b$为偶数且$(a+b)/2$在$a$和$b$之间。

    数据范围:$n≤3 imes 10^{5}$。

    $xfz$智商$=-1$系列题目

    考虑到此题并没有问你存在多少对,而是是否存在,所以不要往统计有多少对上想!

    我们考虑已经加入了前i个数,当前加入的数为x,下面我们需要判断是否存在有一对$a$,$b$满足$a+b=2x$的情况

    令$m=min(n-x,x-1)$,显然满足a+b=2x的$(a,b)$的对数至多为$m$对

    我们令$s1$表示前$i$个数,数值在区间$[x+1,x+m]$中的个数,$s2$表示前i个数,数值在$[x-m,x-1]$中的个数。

    不难发现,若$s1<s2$,则$x$左侧必然有一个数,可以在右侧找到一个数与它匹配。

    $s1>s2$的情况类似。

    所以就可以用树状数组来统计了。

    时间复杂度:$O(nlog n)$。

     1 #include<bits/stdc++.h>
     2 #define M 300005
     3 #define lowbit(x) ((x)&(-x))
     4 using namespace std;
     5 int a[M]={0},n;
     6 void add(int x,int k){for(int i=x;i<=n;i+=lowbit(i)) a[i]+=k;}
     7 int sum(int x){int k=0; for(int i=x;i>0;i-=lowbit(i)) k+=a[i]; return k;}
     8 int main(){
     9     int cas; cin>>cas;
    10     while(cas--){
    11         scanf("%d",&n); memset(a,0,sizeof(a));
    12         int ok=0; for(int i=1;i<=n;i++){
    13             int x; scanf("%d",&x);
    14             if(ok) continue;
    15             add(x,1);
    16             int m=min(n-x,x-1);
    17             int h1=sum(x-1)-sum(x-m-1);
    18             int h2=sum(x+m)-sum(x);
    19             if(h1!=h2) ok=1;
    20         }
    21         if(ok) printf("YES
    ");
    22         else printf("NO
    ");
    23     }
    24 }
  • 相关阅读:
    字符串分割并按大小排序
    为人之气
    RMQ
    线段树
    算法中的数学
    动态规划(DP)
    图的表示
    广度优先搜索(BFS)
    深度优先搜索(DFS)
    MyBatis(3.2.3)
  • 原文地址:https://www.cnblogs.com/xiefengze1/p/10526184.html
Copyright © 2020-2023  润新知