jzoj5557 写诗

Description

给出一个1到n的排列h
要求找出一个三元组满足0

Sample Input

输入样例1
4
1 3 4 2
输入样例2
5
1 5 2 4 3

Sample Output

输出样例1
NO
输出样例2
YES

Data Constraint

n<=3e5

Solution

今天的比赛中最可做的题目,然而还是只想到n^2的做法
看了题解之后恍然大悟
枚举中间的点j
设x=hi或hj
则有2*hj-x>=1,2*hj-x<=n
2*hj-n<=x<=2*hj-1
那我们每次枚举j的时候用树状数组维护符合上面不等式且在j左边的点
设点数为k,这些点的h值之和为sum
若k为奇数,则说明一定有一些点在j的右边,输出yes
若k为偶数
且sum能整除2*hj
则说明一定有一些点在j的左边,输出yes
记得开long long

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const ll N=300005;
ll n,i,j,fl,tr[N],t[N],a[N],k;
ll read(){
    ll sum=0;
    char c=getchar();
    while (c<'0'||c>'9') c=getchar();
    while (c>='0'&&c<='9'){
        sum=sum*10+c-'0';
        c=getchar();}
    return sum;
}
void add(ll x,ll y){
    ll k=x;
    while (x<=n){
        tr[x]+=y;
        t[x]+=k;
        x+=x&(-x);}
}
ll query(ll x){
    int s=0;
    while (x>0){
        s+=tr[x];
        x-=x&(-x);}
    return s;
}
ll find(ll x){
    ll s=0;
    while (x>0){
        s+=t[x];
        x-=x&(-x);
    }
    return s;
}
int main(){
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    n=read();
    fo(i,1,n) a[i]=read();
    add(a[1],1);
    fo(i,2,n-1){
      k=query(min(n,2*a[i]-1))-query(max((ll)0,2*a[i]-n-1));
      if (k%2==1) {
        fl=1;
        break;}
      k=find(min(n,2*a[i]-1))-find(max((ll)0,2*a[i]-n-1));
      if (k%(2*a[i])!=0) {
        fl=1; break;}
        add(a[i],1);
    }
    if (fl) printf("YES\n");
      else printf("NO\n");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值