【xsy1061】排列 树状数组

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

数据范围:n3×105

 

xfz智商=1系列题目

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

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

m=min(nx,x1),显然满足a+b=2x的(a,b)的对数至多为m

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

不难发现,若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\n");
22         else printf("NO\n");
23     }
24 }
复制代码
posted @   AlphaInf  阅读(195)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示