Luogu P5355 [Ynoi2017]由乃的玉米田

Link
开一个桶记录每个数字出现过多少次,同时用bitset维护\(x\)是否出现过。
那么查询是否有两个数的差为\(x\)就是把bitset右移\(x\)位然后与自己,如果有位置为\(1\)那么就说明存在。
查询是否有两个数的和为\(x\)也可以类似地做,多开一个bitset维护\(10^5-x\)是否出现过。
查询是否有两个数的积为\(x\)可以直接枚举因数查询,注意特判\(x=0\)的情况。
最后是查询是否有两个数的商为\(x\),首先特判\(x=0\)的情况,对于\(x\ge64\)的数据,我们可以暴力枚举判断。
对于\(1\le x<64\)的,我们把所有\(x\)相同询问的放一起并按左端点降序排序,用树状数组维护一下以每个点为左端点的最左右端点就好了。
时间复杂度是\(O(\frac{n^2}{64}+n\sqrt n+64n\log n)\)。
(实际上除法那里最优的分治边界应该是\(\sqrt{\frac n{\log n}}\),这样复杂度就是\(O(\frac{n^2}{64}+n\sqrt{n\log n})\),不过\(64\)也差不多)

#pragma GCC optimize(3)
#include<cmath>
#include<cstdio>
#include<cctype>
#include<bitset>
#include<cstring>
#include<algorithm>
namespace IO
{
    char ibuf[(1<<21)+1],*iS,*iT;
    char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);}
    int read(){int x=0,c=Get();while(!isdigit(c))c=Get();while(isdigit(c))x=x*10+c-48,c=Get();return x;}
}using IO::read;
using std::sort;
using std::bitset;
int min(int a,int b){return a<b? a:b;}
const int N=100007,U=100000,inf=0x3f3f3f3f;
bitset<N>S,T;
int n,m,bel[N],t[N],pos[N],a[N],ans[N];
struct node{int o,l,r,x,id;}q[N],p[N];
int operator<(const node&a,const node&b){return bel[a.l]==bel[b.l]? a.r<b.r:a.l<b.l;}
void add(int x){if(++t[x]==1)S[x]=T[U-x]=1;}
void del(int x){if(!--t[x])S[x]=T[U-x]=0;}
int askmul(int x){if(!x)return S[0];for(int i=1;i*i<=x;++i)if(!(x%i)&&S[i]&&S[x/i])return 1;return 0;}
int askdiv(int x){if(!x)return S[0]&&S.count()>1;for(int i=1,j=x;j<=U;++i,j+=x)if(S[i]&&S[j])return 1;return 0;}
void update(int p,int v){for(;p<=n;p+=p&-p)t[p]=min(t[p],v);}
int query(int p){int r=inf;for(;p;p^=p&-p)r=min(r,t[p]);return r;}
int main()
{
    n=read(),m=read();int c=0,B=sqrt(n)+rand()%5;
    for(int i=1;i<=n;++i) a[i]=read(),bel[i]=(i-1)/B+1;
    for(int i=1;i<=m;++i) q[i]={read(),read(),read(),read(),i};
    sort(q+1,q+m+1);
    for(int i=1,L=1,R=0;i<=m;++i)
    {
    int l=q[i].l,r=q[i].r,x=q[i].x;
    if(q[i].o==4&&q[i].x<64&&q[i].x) {p[++c]=q[i];continue;}
    while(l<L) add(a[--L]);
    while(R<r) add(a[++R]);
    while(L<l) del(a[L++]);
    while(r<R) del(a[R--]);
    if(q[i].o==1) ans[q[i].id]=(S&S<<x).any();
    else if(q[i].o==2) ans[q[i].id]=(S&T>>(U-x)).any();
    else if(q[i].o==3) ans[q[i].id]=askmul(x);
    else ans[q[i].id]=askdiv(x);
    }
    sort(p+1,p+c+1,[](const node&a,const node&b){return a.x<b.x||(a.x==b.x&&a.l>b.l);});
    for(int l=1,r;l<=c;l=r+1)
    {
    for(r=l;p[r+1].x==p[l].x&&r<c;++r);
    memset(t,0x3f,sizeof t),memset(pos,0x3f,sizeof pos);
    for(int i=l,j=n;i<=r;++i)
        {
            for(;j>=p[i].l;--j)
            {
        pos[a[j]]=j;
        if(1ll*a[j]*p[l].x<=U) update(j,pos[a[j]*p[l].x]);
        if(!(a[j]%p[l].x)) update(j,pos[a[j]/p[l].x]);
            }
        ans[p[i].id]=p[i].l>p[i].r? 0:query(p[i].r)<=p[i].r;
        }
    }
    for(int i=1;i<=m;++i) puts(ans[i]? "yuno":"yumi");
}

原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12217302.html

时间: 2024-10-11 12:47:57

Luogu P5355 [Ynoi2017]由乃的玉米田的相关文章

[BZOJ]4810: [Ynoi2017]由乃的玉米田

Time Limit: 30 Sec  Memory Limit: 256 MB Description 由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐. 由乃认为玉米田不美,所以她决定出个数据结构题 这个题是这样的: 给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1,2,3选出的这两个

BZOJ4810 [Ynoi2017]由乃的玉米田

本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/转载请注明出处,侵权必究,保留最终解释权! 题目链接:BZOJ4810 正解:$bitset$+莫队算法 解题报告: 考虑直接上$bitset$会$MLE$,我们用莫队来优化空间,不用每个点都开一个. 维护一个$cnt$数组,表示每种值的出现次数,那么我可以用$bitset$维护每种权值是否出现过.

bzoj 4810: [Ynoi2017]由乃的玉米田 莫队 bitset

bitset大概就是让你轻松建立一个很长的二进制数来存东西,并提供了快捷的操作和优美的常数. #include <bitset> bitset <32> b;32为长度 需要引用头文件,定义一个bitset. stl的东西,所以从0开始. 支持左右移. 支持下标访问修改. b.any() b中是否存在置为1的二进制位 b.none() b中不存在置为1的二进制位 b.count() b中置为1的二进制位的个数 b.size() b中二进制位的个数 b[pos] 访问b中在pos处的

bzoj3594 [Scoi2014]方伯伯的玉米田

3594: [Scoi2014]方伯伯的玉米田Time Limit: 60 Sec Memory Limit: 128 MBSubmit: 1437 Solved: 647[Submit][Status][Discuss]Description方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把

bzoj 3594: [Scoi2014]方伯伯的玉米田 dp树状数组优化

3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 314  Solved: 132[Submit][Status] Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把这个区间的

3594: [Scoi2014]方伯伯的玉米田

3594: [Scoi2014]方伯伯的玉米田 Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可以选择一个区间,把这个区间的玉米全部拔高1单位高度,他可以进行最多K次这样的操作.拔玉米则可以随意选择一个集合的玉米拔掉.问能最多剩多少株玉米,来构成一排美丽的玉米. Input 第1行包含

bzoj 4810 由乃的玉米田 - bitset - 莫队算法

由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐. 由乃认为玉米田不美,所以她决定出个数据结构题 这个题是这样的: 给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是 否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1 ,2,3选出的这两个数可以是同一个位置的数 Input 第一行两个数n,m 后面一行n个数表示ai 后面m行每行四个数op

洛谷 P1879 [USACO06NOV]玉米田Corn Fields

P1879 [USACO06NOV]玉米田Corn Fields 题目描述 Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the

BZOJ 3594[Scoi2014]方伯伯的玉米田

题面: 3594: [Scoi2014]方伯伯的玉米田 Time Limit: 60 Sec  Memory Limit: 128 MBSubmit: 1403  Solved: 630[Submit][Status][Discuss] Description 方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美.这排玉米一共有N株,它们的高度参差不齐.方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列.方伯伯可