首页 > 其他分享 >[Ynoi2017] 由乃的玉米田

[Ynoi2017] 由乃的玉米田

时间:2024-08-23 16:28:23浏览次数:13  
标签:pre vis1 int 玉米田 Ynoi2017 100000 using op

题目链接 : [Ynoi2017] 由乃的玉米田

弱化版 : 小清新人渣的本愿

这两道题都是看会不会用bitset,bitset大胜利

  1. 减操作 : 用一个bitset \(vis1\) 记录一个数是否出现,如果有就是\((vis1\And(vis>>x)).count()\ge 1\),其实就是看是否有数\(a\)和数\(a+x\)同时出现

  2. 加操作 : 同减操作,但是要转化一下,就是\(a+b=x\Leftrightarrow a-(100000-b)=x-100000\)。记录一个相反的bitset \(vis2\),然后就是判断是否 \((vis1\And(vis2>>(100000-x))).count()\ge 1\)(因为vis2是相反的bitset,所以不是右移\(x-100000\)位而是\(100000-x\)位)

  3. 乘操作 : \(O(\sqrt x)\)暴力跑即可

  4. 除操作 : 根号分治

    1. \(x\ge \sqrt{100000}\)的暴力跑,复杂度是正确的\(O(\sqrt{n})\)
    2. 对于\(x< \sqrt{100000}\)的,将其特殊处理

    定义两个数组 : \(pre_x\)表示\(x\)上一次(包括当前位置,因为一个位置可以重复选两次)出现的位置,\(lastpos_i\)表示到\(i\)时最后一个合法点对\((i,j)(i\le j)\)中\(i\)的位置。

    然后将所有\(op = 4 \And x<\sqrt{100000}\)的单独记录出来,单独处理。

    枚举\(x\),然后用一个指针\(i\; O(n)\)扫一遍\(a\),假设当前扫到的位置为\(i\),记录当前最后一个合法点对\((i,j)\)中\(i\)的位置为\(res\),依次执行以下操作 :

    1. 用\(i\)替换\(pre_{a_i}\)
    2. 如果\(a_i\times x\le 100000\),那么\(res = \max(res,pre_{a_i\times x})\)
    3. 如果\(a_i\bmod x = 0\),那么\(res = \max(res,pre_{\frac{a_i}{x}})\)

    最后统计一下答案,就是比较\(l\)与\(lastpos_r\)的大小关系,如果\(l>lastpos_r\)则无解。

预处理的复杂度是\(O(n\sqrt n)\),莫队的复杂度是\(O(n(\sqrt{n} + \frac{n}{w}))\)的,可以通过,无需卡常

点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
#ifdef LOCAL
    FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
    // FILE *ErrFile=errfile("err.err");
#else
    FILE *Infile = stdin,*OutFile = stdout;
    //FILE *ErrFile = stderr;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
const int N = 1e5 + 10,M = 330;
int n,m,a[N],L[M],R[M],pos[N],len,ct[N];
struct node{int op,l,r,x,id;}q[N];int cnt = 0;
bool ans[N];
struct Node{int l,r,id;};
vector<Node> p[M];
int pre[N],lastpos[N];
inline void solve(){
    cin>>n>>m;
    for(int i = 1;i <= n; ++i) cin>>a[i];
    for(int i = 1,op,l,r,x;i <= m; ++i){
        cin>>op>>l>>r>>x;
        if(op == 4 && x < M) p[x].emplace_back((Node){l,r,i});
        else q[++cnt] = {op,l,r,x,i};
    }
    for(auto i:p[1]) ans[i.id] = true;
    for(int now = 2;now < M; ++now){
        if(p[now].empty()) continue;
        int res = 0;
        memset(lastpos,0,sizeof lastpos);
        memset(pre,0,sizeof pre);
        for(int i = 1;i <= n; ++i){
            int y = a[i];
            pre[y] = i;
            if(now * y <= 100000) res = max(res,pre[now*y]);
            if(y % now == 0) res = max(res,pre[y/now]);
            lastpos[i] = res;
        }
        for(auto i : p[now]) ans[i.id] = (i.l <= lastpos[i.r]);
    }

    len = sqrt(n);
    for(int i = 1;i <= len; ++i) L[i] = R[i - 1] + 1,R[i] = i * len;
    if(R[len] < n) len ++, L[len] = R[len - 1] + 1,R[len] = n;
    for(int i = 1;i <= len; ++i) for(int j = L[i];j <= R[i]; ++j) pos[j] = i;
    sort(q+1,q+1+cnt,[](node x,node y){return (pos[x.l]==pos[y.l]?(pos[x.l]&1?x.r<y.r:x.r>y.r):x.l<y.l);});

    bitset<N> vis1,vis2;
    int left = 1,right = 0;
    auto add = [&](int x) -> void{
        if(!ct[x])vis1[x] = vis2[100000 - x] = true;
        ct[x]++;
    };
    auto del = [&](int x) -> void{
        ct[x]--;
        if(!ct[x]) vis1[x] = vis2[100000 - x] = false;
    };
    for(int i = 1;i <= cnt; ++i){
        int l = q[i].l,r = q[i].r,op = q[i].op,x = q[i].x;
        while(left > l) add(a[--left]);
        while(right < r) add(a[++right]);
        while(left < l) del(a[left++]);
        while(right > r) del(a[right--]);
        if(op == 1) ans[q[i].id] = (vis1&(vis1>>x)).count();
        if(op == 2) ans[q[i].id] = (vis1&(vis2>>(100000-x))).count();
        if(op == 3){
            int k = sqrt(x);
            for(int j = 1;j <= k; ++j){
                if(x % j == 0 && vis1[j] && vis1[x/j]){ans[q[i].id] = true;break;}
            }
        }
        if(op == 4){
            for(int j = 1;j <= 100000/x; ++j) if(vis1[j] && vis1[j*x]){ans[q[i].id] = true;break;}
        }
    }
    for(int i = 1;i <= m; ++i) cout<<(ans[i]?"yuno\n":"yumi\n");
}
signed main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cout.tie(nullptr)->sync_with_stdio(false);
    solve();   
}

标签:pre,vis1,int,玉米田,Ynoi2017,100000,using,op
From: https://www.cnblogs.com/hzoi-Cu/p/18376331

相关文章

  • [SCOI2014] 方伯伯的玉米田 题解
    对于每次修改的区间以及其左边序列和右边序列,共三种情况:1.区间内比两侧低的还是低2.区间内比两侧低的变得比两侧高了3.区间内比两侧高的还是高那么现在又面临一个问题:在区间内变化后,对答案,即最长不下降子序列有什么影响。对区间左边:可能会使其最长不下降子序列增长对区间......
  • 51nod-3928方伯伯的玉米田
    https://class.51nod.com/Html/Textbook/ChapterIndex.html#textbookId=126&chapterId=338https://class.51nod.com/Html/Textbook/Problem.html#problemId=3928&textbookChapterId=725保证右端点为\(n\)是因为如果不是这样操作,可能导致后面的数大小关系发生变化,而如果保证了......
  • 327. 玉米田
    //327.玉米田.cpp:此文件包含"main"函数。程序执行将在此处开始并结束。//#include<iostream>usingnamespacestd;/*https://www.acwing.com/problem/content/329/农夫约翰的土地由M×N个小方格组成,现在他要在土地里种植玉米。非常遗憾,部分土地是不育的,无......
  • #分块,二分#洛谷 5356 [Ynoi2017] 由乃打扑克
    题目支持区间加和区间查询第\(k\)小分析分块之后给每个整块排序,这样修改的时候整块打标记,散块直接分开把需要加的部分暴力加之后归并,就是\(O(\sqrt{n})\)的查询的话,如果只有散块直接归并出结果,否则二分答案,加上小块合并成的整块,相当于是整体二分,就是\(O(\sqrt{n}\log{a_......
  • luoguP3287 [SCOI2014] 方伯伯的玉米田
    题目描述方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。这排玉米一共有NN株,它们的高度参差不齐。方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列。方伯伯可以选择一个区间,把这......
  • P3287 [SCOI2014] 方伯伯的玉米田
    首先每次选择的区间结尾都可以换成\(n\),仍然保持单调不降,我们就按这个策略拔高玉米。令\(f_{i,j}\)表示\(1\simi\)这段前缀进行了\(j\)次操作,第\(i\)株玉米不被拔掉,所能剩下最多的玉米数量:\[f_{i,j}=\max\{f_{p,q}|p<i,q<j,a_p+q\leqa_i+j\}+1\]枚举\(i\),剩下两个......
  • LuoguP5354 [Ynoi2017]由乃的OJ题解
    P5354[Ynoi2017]由乃的OJPreface自己的由乃题一血,写篇题解纪念一下。Description给定一颗\(n\)个结点的树,每个结点都有一个权值\(a_i\)和一个位运算符\(\mathrm{......
  • [SCOI2014]方伯伯的玉米田题解
    [SCOI2014]方伯伯的玉米田题目描述方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。这排玉米一共有\(N\)株,它们的高度参差不齐。方伯伯认为单调不下降序......
  • P3287 [SCOI2014]方伯伯的玉米田
    \(\mathcal{Link}\)显然,每次区间加的一定是一段后缀。设\(f(i,j)\)表示必选第\(i\)个位置用了\(j\)次的最大保留值。\[f(i,j)=\max\{f(k,l)\}(k\leqi,l\leqj,a......
  • P3287 [SCOI2014]方伯伯的玉米田
    题意进行最多\(k\)次区间\(+1\)操作,使得序列中的最长不下降子序列最长。分析首先,拔高的区间一定是\([i,n]\)这种的,因为拔高一段区间,对于区间内部的相对高度是不变......