zoukankan      html  css  js  c++  java
  • 洛谷$P4755 Beautiful Pair$ 最大值分治

    正解:最大值分治

    解题报告:

    传送门$QwQ$

    昂考虑如果已经钦定了点$x$是这个$max$了,然后现在要求有多少对$[l,r]$满足$a_x=maxleft{a_i ight},iin[l,r]$,且$a_lcdot a_rleq a_x$

    现在枚举$l$,发现$r$就有一个范围了,就$a_rleq frac{a_x}{a_l}$,这个就可以用主席树维护下就成嘛$QwQ$(我开始想用树状数组的,,,然后想了下发现因为是分治所以每次树状数组都要重建复杂度是错的$kk$,所以还是去用主席树趴$QwQ$

    所以就基本上能得出这题的基本思路了?首先找到区间最大值$x$,先分别求出$x$两侧的答案,然后统计跨过$x$的贡献.考虑枚举$l$,然后对于$r$就直接树状数组搞下就行.但是发现如果$l$中的点太多也不可,所以考虑枚举$size$较小的那一边.

    这个的复杂度和启发式合并的复杂度是一样的,就$O(nlogn)$,然后加上树状数组的复杂度,总复杂度就两个$log$的

    $over$?

     

    #include<bits/stdc++.h>
    using namespace std;
    #define il inline
    #define gc getchar()
    #define mp make_pair
    #define int long long
    #define ri register int
    #define rc register char
    #define rb register bool
    #define rp(i,x,y) for(ri i=x;i<=y;++i)
    #define my(i,x,y) for(ri i=x;i>=y;--i)
    #define lb(x) lower_bound(b+1,b+1+num,x)-b
    #define ub(x) upper_bound(b+1,b+1+num,x)-b
    
    const int N=1e5+10;
    int n,a[N],b[N],st[20][N],num,rt[N],nod_cnt,lg[N];
    struct node{int num,ls,rs;}tr[N*64];
    
    il int read()
    {
        rc ch=gc;ri x=0;rb y=1;
        while(ch!='-' && (ch>'9' || ch<'0'))ch=gc;
        if(ch=='-')ch=gc,y=0;
        while(ch>='0' && ch<='9')x=(x<<1)+(x<<3)+(ch^'0'),ch=gc;
        return y?x:-x;
    }
    il int cmp(ri gd,ri gs){return a[gd]>=a[gs]?gd:gs;}
    il void pre()
    {
        lg[0]=-1;rp(i,1,n)st[0][i]=i,lg[i]=lg[i>>1]+1;
        rp(i,1,lg[n])
            rp(j,1,n-(1<<i)+1)st[i][j]=cmp(st[i-1][j],st[i-1][j+(1<<(i-1))]);
    }
    il int ask(ri l,ri r){ri len=lg[r-l+1];return cmp(st[len][l],st[len][r-(1<<len)+1]);}
    int modify(ri nw,ri l,ri r,ri to)
    {
        ri x=++nod_cnt;tr[x]=tr[nw];++tr[x].num;if(l==r)return x;
        ri mid=(l+r)>>1;to<=mid?tr[x].ls=modify(tr[nw].ls,l,mid,to):tr[x].rs=modify(tr[nw].rs,mid+1,r,to);
        return x;
    }
    int query(ri nw,ri l,ri r,ri to)
    {
        if(r<=to)return tr[nw].num;
        ri mid=(l+r)>>1,ret=query(tr[nw].ls,l,mid,to);
        if(mid<to)ret+=query(tr[nw].rs,mid+1,r,to);
        return ret;
    }
    int solv(ri l,ri r)
    {
        if(l>r)return 0;
        if(l==r)return b[a[l]]==1;
        ri mid=ask(l,r),sum=0;sum+=solv(l,mid-1);sum+=solv(mid+1,r);//printf("l=%d r=%d sum=%d mid=%d solv(%d,%d),solv(%d,%d)
    ",l,r,sum,mid,l,mid-1,mid+1,r);
        ri tl=l,tr=mid,askl=mid,askr=r;if(mid-l+1>r-mid)swap(tl,askl),swap(tr,askr);
        //printf("tl=%d tr=%d askl=%d askr=%d
    ",tl,tr,askl,askr);
        rp(i,tl,tr)
        {
            ri lim=ub(b[a[mid]]/b[a[i]])-1;if(lim)sum+=query(rt[askr],1,num,lim)-query(rt[askl-1],1,num,lim);
        }
        //printf("l=%d r=%d sum=%d
    ",l,r,sum);
        return sum;
    }
    
    signed main()
    {
        //freopen("4755.in","r",stdin);freopen("4755.out","w",stdout);
        n=read();rp(i,1,n)a[i]=b[i]=read();sort(b+1,b+1+n);num=unique(b+1,b+1+n)-b-1;
        rp(i,1,n)a[i]=lb(a[i]),rt[i]=modify(rt[i-1],1,num,a[i]);
        pre();printf("%lld
    ",solv(1,n));
        return 0;
    }
    View Code

     

  • 相关阅读:
    281. Zigzag Iterator
    298. Binary Tree Longest Consecutive Sequence
    482. License Key Formatting
    361. Bomb Enemy
    373. Find K Pairs with Smallest Sums
    304. Range Sum Query 2D
    308. Range Sum Query 2D
    307. Range Sum Query
    303. Range Sum Query
    247. Segment Tree Query II
  • 原文地址:https://www.cnblogs.com/lqsukida/p/11494906.html
Copyright © 2011-2022 走看看