其他分享
首页 > 其他分享> > 牛客练习赛96(未完工)

牛客练习赛96(未完工)

作者:互联网

A.小y的平面

签到题,存点然后排序。一定满足 Xi<=Xi+1且Yi<=Yi+1。若不满足直接输出No,否则输出Yes。

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int x,y;
}t[1000006];
bool cmp(node a,node b)
{
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
int main()
{
    int n,xx=0,yy=0;
    cin>>n;
    for(int i=0;i<n;i++)
        cin>>t[i].x>>t[i].y;
    sort(t,t+n,cmp);
    for(int i=0;i<n;i++)
    {
        if(xx<=t[i].x&&yy<=t[i].y)
        {
            xx=t[i].x;
            yy=t[i].y;
        }
        else
        {
            puts("NO");
            return 0;
        }
    }
    puts("YES");
    return 0;
}
View Code

B.小y的树

计数题,统计每条边的边权。对于一颗树来说,选择任意一条边并将其砍断,可以将树分成两部分,其中一部分仍然是个满k叉树,另一部分不是。我们可以发现满k叉树每一层的节点树为k0,k1,...kn-1

所以对于链接第i层和第i+1层的边,砍断以后会得到一颗n-i层的树(1<=i<n),所以很容易计算得到较小部分的节点数量a,较大部分的节点数量用总数减a即可。从两颗树中间任意取一个点,这两个点的路径都会经过砍断的这条边。所以对于这条边的贡献是a*b。由满k叉树的对称性,同一层的边具有相同的权值。不难推出,链接第i层和第i+1层的边有m=ki条。所以这一层所有边的权和为a*b*m.

由于数据规模较大,我们存储节点数量的时候需要mod1e9+7,这时可能导致sum-a是个负数。为了避免这种情况,计算时要算(sum-a)%mod+mod。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
int f[1000006];
int v[1000006];
signed main()
{
    int n,k,ans=0;
    cin>>n>>k;
    //从第0层到第n-1层,共有n层,每层有k^n个节点
    v[1]=f[1]=1;
    //f[i]存深度为i的k叉树有多少个节点
    for(int i=2;i<=n;i++)
    {
        v[i]=v[i-1]*k%mod;//第i层有这么多个点
        f[i]=(f[i-1]+v[i])%mod;//i层的树有这么多点
    }
    for(int i=1;i<n;i++)//从第一层到第n层统计边
    {
        int a=f[i];
        int b=(f[n]-a)%mod+mod;
        int m=v[n-i+1];
        ans=(ans+a*b%mod*m%mod)%mod;
    }
    cout<<ans<<endl;
}
View Code

C.小y的序列

计数题,二分,st表。

对于固定的左端点L,[L,L]....[L,N]这些区间的max是非递减的,min是非递增的。所以max-min保持了单调性。在这个存在单调性的序列中,用二分找到满足题意的最左点r1和最右点r2,即对于任意的R∈[r1,r2],[L,R]都满足题意。那么左端点L对答案的贡献即为r2-r1+1。

然后从1到n枚举左端点即可。在二分时不断查询[l,mid]的最大值和最小值。

 

对于RMQ问题,一般是采用线段树来完成O(log)查找。但是这题数据规模1e6卡了2log,并且是静态区间最值问题,所以可以改用ST表来维护静态区间最值。ST表可以实现O(1)查找,效率要高不少。

/*刚发现有人线段树也过了,一会研究一下。*/

巨佬用的线段树+双指针1log过的,确实妙。到时候补一下双指针(大弱项qwq

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+6;
int n,k,a[maxn];
long long ans=0;
struct node
{
    int l,r,maxx,minn;
}t[maxn<<2];
void build(int k,int l,int r)
{
    t[k].l=l,t[k].r=r;
    if(l==r)  
    {
        t[k].maxx=t[k].minn=a[l];
        return;
    }
    int mid=(t[k].l+t[k].r)/2;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    t[k].maxx=max(t[k<<1].maxx,t[k<<1|1].maxx);
    t[k].minn=min(t[k<<1].minn,t[k<<1|1].minn);
}
int query_max(int k,int l,int r)
{
    if(l<=t[k].l&&t[k].r<=r)
        return t[k].maxx;
    int mid=(t[k].l+t[k].r)/2;
    int ans=0;
    if(l<=mid)
        ans=max(ans,query_max(k<<1,l,r));
    if(mid<r)
        ans=max(ans,query_max(k<<1|1,l,r));
    return ans;
}
int query_min(int k,int l,int r)
{
    if(l<=t[k].l&&t[k].r<=r)
        return t[k].minn;
    int mid=(t[k].l+t[k].r)/2;
    int ans=10000006;
    if(l<=mid)
        ans=min(ans,query_min(k<<1,l,r));
    if(mid<r)
        ans=min(ans,query_min(k<<1|1,l,r));
    return ans;
}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    build(1,1,n);
    for(int i=1;i<=n;i++)
    {
        long long l=i,r=n;
        while(l<r)
        {
            long long mid=(l+r)>>1;
            if(query_max(1,i,mid)-query_min(1,i,mid)>=k)
                r=mid;
            else
                l=mid+1;
        }
        if(query_max(1,i,l)-query_min(1,i,l)==k)
        {
            long long ll=i,rr=n;
            while(ll<rr)
            {
                long long mid=(ll+rr+1)>>1;
                if(query_max(1,i,mid)-query_min(1,i,mid)<=k)
                    ll=mid;
                else
                    rr=mid-1;
            }
            ans+=ll-l+1;
        }
    }
    printf("%lld\n",ans);
}
线段树TLE
#include<bits/stdc++.h>
using namespace std;

const int N=1e6+10,M=21;
int n,k,a[N],stn[N][M],stx[N][M];
int lg[N];

void init()
{    
    for(int i=1;i<M;i++)
        for(int j=1;j+(1<<i)-1<=n;j++)
    {
        stx[j][i]=max(stx[j][i-1],stx[j+(1<<(i-1))][i-1]);
        stn[j][i]=min(stn[j][i-1],stn[j+(1<<(i-1))][i-1]);
    }
    for(int i=2;i<=n;i++) lg[i]=lg[i>>1]+1;
}

int qurey(int l,int r)
{
    int t=lg[r-l+1];
    return max(stx[l][t],stx[r-(1<<t)+1][t])-min(stn[l][t],stn[r-(1<<t)+1][t]);
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    
    cin>>n>>k;
    for(int i=1;i<=n;i++)
    {
        cin>>stx[i][0];
        stn[i][0]=stx[i][0];
    }
    init();
    long long ans=0;
    for(int i=1;i<=n;i++)
    {
        int l=i,r=n;
        while(l<r)
        {
            int mid=(l+r)>>1;
            if(qurey(i,mid)>=k) r=mid;
            else l=mid+1;
        }
        int z=r;
        if(qurey(i,z)!=k) continue;
        l=i,r=n;
        while(l<r)
        {
            int mid=(l+r+1)>>1;
            if(qurey(i,mid)<=k) l=mid;
            else r=mid-1;
        }
        ans=ans+l-z+1;
    }
    cout<<ans;
    
    return 0;
}
ST表AC

DEF待补

标签:练习赛,int,max,mid,long,牛客,query,stx,96
来源: https://www.cnblogs.com/brucekz/p/15935402.html