首页 > 其他分享 >[Ynoi2018] 未来日记

[Ynoi2018] 未来日记

时间:2024-11-13 15:42:45浏览次数:1  
标签:Ynoi2018 rt rep int s2 sum fa 未来 日记

[Ynoi2018] 未来日记

老早之前就想写了,人生中第一道大分块,调了一上午+下午一个小时,对拍了不知道多少万组,终于过了。

\[\Huge{本题不卡常本题不卡常本题不卡常本题不卡常本题不卡常本题不卡常本题不卡常} \]

\[\Huge{快来写快来写快来写快来写快来写快来写快来写快来写快来写快来写快来写} \]

solution

由于是Ynoi,考虑分块

数据范围\(10^5\),加上这么诡异的操作,先想分块。

区间rank让人以为是[Ynoi2017] 由乃打扑克这道题,但是如果按照由乃打扑克的思路这题的操作就做不了了。

分块是有自己复杂度的就是\(O(\sqrt{n})\)而不是\(O(\log n)\)这意味着分块其实和log的数据结构以及二分法并不是很搭(因为分块的结构本质上就不支持二分)如果我们需要强行嵌入\(log\)的数据结构的话在绝大部分情况下都会使复杂度凭空多出个\(log\)来,这在强调常数的根号算法中绝对是致命的。——来自shadowice1984的题解。

所以可以考虑时间复杂度同为\(O(\sqrt{n})\)的块状数组,由于\(V\le 10^5\),考虑对值域分块,具体的,就是记\(s1_{i,j}\)表示前\(i\)个序列块中有多少个数在\(j\)值域块中,\(s2_{i,j}\)表示前\(i\)块中有多少个\(j\),查询时先遍历值域块,确定答案所在值域块的位置,然后再遍历值域块找到答案。

简单的查询就处理完了,那么这个逆天的修改如何处理,有一个经典套路就是用并查集来维护,具体的,记\(rt_{i,x}\)表示第\(i\)块中值为\(x\)的数的代表元,这里我用的是每块中第\(1\)个数的位置。然后用并查集维护位置就可以了,整块就直接令\(rt_{i,y}=\min\{rt_{i,y},rt_{i,x}\}\)即可,考虑散块,仍然考虑暴力修,但是如果每个都修爆炸,只需要重构\(rt_{i,x},rt_{i,y}\)为根的子树就行。

时间复杂度\(O((n+m)\sqrt{n})\),实现优秀,cin/cout关了同步流都能过!!!

挂一个你谷第2优解。

点此查看代码
#include<bits/stdc++.h>
using namespace std;
#define rep(i,s,t,p) for(int i = s;i <= t; i += p)
#define drep(i,s,t,p) for(int i = s;i >= t; i -= p)
#ifdef LOCAL
    FILE *InFile = freopen("in.in","r",stdin),*OutFile = freopen("out.out","w",stdout);
    FILE *ErrFile = freopen("err.err","w",stderr);
#else
    FILE *InFile = stdin,*OutFile = stdout;
#endif
using ll=long long;using ull=unsigned long long;
using db = double;using ldb = long double;
namespace IO{
    const int size = 1<<24;
    struct IO{
        char buf[size],*p1,*p2,obuf[size],*op = obuf;
        #define gc() ((p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2))?EOF:*p1++)
        inline void pc(char x){if(__builtin_expect(op - obuf == size,1)) fwrite(obuf,1,size,stdout);*op++ = x;}
        ~IO(){fwrite(obuf,1,op-obuf,stdout);}
        template<class T>inline void read(T &x){x = 0;char s = gc();for(;s < '0' || '9' < s;s = gc());for(;'0' <= s && s <= '9';s = gc())x = (x<<1)+(x<<3)+(s^48);}
        template<class T,class... Args>inline void read(T &x,Args&... argc){read(x);read(argc...);}
        template<class T>
        inline void write(T x){static int sta[30],top = 0;do sta[++top] = x%10;while(x /= 10);while(top) pc(sta[top--]+'0');}
        inline void write(char x){pc(x);}
        template<class T,class... Args>inline void write(T x,Args... argc){write(x);write(argc...);}
    }io;
    #define read io.read
    #define write io.write
}using IO::io;
/*
诶不是,我要处理啥啊。
对于值域块处理1~i中有多少个,然后还要处理每个数。
*/
const int N = 1e5 + 1,SN = N/310,V = 1e5 + 1,SV = N/310,RV = 1e5,cjs = 123;
int n,m,a[N];
int L1[SN],R1[SN],p1[N],lens,sizs;
int L2[SV],R2[SV],p2[V],lenv,sizv;
int s1[SN][SV];//前i块中有多少个数在j块中
int s2[SN][V];//前i块中有多少个j
int s3[SN][V];//第i块中有多少个j
int rt[SN][V],fa[N];
int ct1[SV],ct2[V];//查询时用来记录散块
inline int get_fa(int x){while(x^fa[x]) x = fa[x] = fa[fa[x]];return x;}
inline void Merge(int x,int y){if(x > y) swap(x,y);fa[y] = x;}
//将y并到x中,顺序有关。 
inline void upd(int l,int r,int x,int y){
    int p = p1[l],q = p1[r],px = p2[x],py = p2[y],sum = 0;
    auto rbuild = [&](int p,int l,int r){
        if(!s3[p][x]) return 0;
        int res = 0,ff = rt[p][x];
        vector<int> sonx,sony;
        rep(i,L1[p],R1[p],1){
            if(get_fa(i) == rt[p][x]){
                if(i < l || i > r) sonx.emplace_back(i);
                else sony.emplace_back(i),++res;
            }
            if(fa[i] == rt[p][y]) sony.emplace_back(i);
        }
        rt[p][x] = rt[p][y] = 0;
        for(auto i:sonx){
            if(!rt[p][x]) rt[p][x] = fa[i] = i;
            else fa[i] = rt[p][x];
            a[i] = x;
        }
        for(auto i:sony){
            if(!rt[p][y]) rt[p][y] = fa[i] = i;
            else fa[i] = rt[p][y];
            a[i] = y;
        }
        s3[p][x] -= res,s3[p][y] += res;sum += res;
        return res;
    };
    if(p == q){
        int res = rbuild(p,l,r);
        if(!res) return;
        rep(i,p,sizs,1){
            s1[i][px] -= res;s1[i][py] += res;
            s2[i][x] -= res,s2[i][y] += res;
        }
        return;
    }
    rbuild(p,l,R1[p]);
    s1[p][px] -= sum;s1[p][py] += sum;
    s2[p][x] -= sum,s2[p][y] += sum;

    rep(i,p+1,q-1,1){
        if(s3[i][x]){
            if(!rt[i][y]) rt[i][y] = rt[i][x],a[rt[i][x]] = y;
            else Merge(rt[i][y],rt[i][x]);
            fa[rt[i][y] = get_fa(rt[i][y])] = rt[i][y];rt[i][x] = 0;
            a[get_fa(rt[i][y])] = y;
            sum += s3[i][x],s3[i][y] += s3[i][x],s3[i][x] = 0;
        }
        s1[i][px] -= sum,s1[i][py] += sum;
        s2[i][x] -= sum,s2[i][y] += sum;
    }
    rbuild(q,L1[q],r);
    s1[q][px] -= sum;s1[q][py] += sum;
    s2[q][x] -= sum,s2[q][y] += sum;
    if(!sum) return;
    rep(i,q+1,sizs,1){
        s1[i][px] -= sum;s1[i][py] += sum;
        s2[i][x] -= sum,s2[i][y] += sum;
    }
}
inline int qry(int l,int r,int k){
    int p = p1[l],q = p1[r];
    if(p == q){
        vector<int> res;
        rep(i,l,r,1) res.emplace_back(a[get_fa(i)]);
        nth_element(res.begin(),res.begin()+k-1,res.end());
        return *(res.begin()+k-1);
    }
    rep(i,l,R1[p],1) ++ct2[a[get_fa(i)]],++ct1[p2[a[get_fa(i)]]];
    rep(i,L1[q],r,1) ++ct2[a[get_fa(i)]],++ct1[p2[a[get_fa(i)]]];
    int sum = 0,pos = 0,ans = 0;
    rep(i,1,sizv,1){
        sum += ct1[i] + s1[q-1][i] - s1[p][i];
        if(sum >= k){sum -= ct1[i] + s1[q-1][i] - s1[p][i];pos = i;break;}
    }
    rep(j,L2[pos],R2[pos],1){
        if(sum + ct2[j] + s2[q-1][j] - s2[p][j] >= k){ans = j;break;}
        sum += ct2[j] + s2[q-1][j] - s2[p][j];
    }
    rep(i,l,R1[p],1) ct2[a[get_fa(i)]]--,ct1[p2[a[get_fa(i)]]]--;
    rep(i,L1[q],r,1) ct2[a[get_fa(i)]]--,ct1[p2[a[get_fa(i)]]]--;
    return ans;
}
inline void solve(){
    read(n,m);rep(i,1,n,1) read(a[i]),fa[i] = i;

    lens = 500,sizs = n/lens;
    rep(i,1,sizs,1) L1[i] = R1[i-1]+1,R1[i] = i*lens;
    if(R1[sizs] < n) sizs++,L1[sizs] = R1[sizs-1]+1,R1[sizs] = n;

    lenv = sqrt(RV),sizv = RV/lenv;
    rep(i,1,sizv,1) L2[i] = R2[i-1]+1,R2[i] = i*lenv;
    if(R2[sizv] < RV) sizv++,L2[sizv] = R2[sizv-1]+1,R2[sizv] = RV;

    rep(i,1,sizv,1) rep(j,L2[i],R2[i],1) p2[j] = i;

    rep(i,1,sizs,1){
        rep(j,L1[i],R1[i],1){
            p1[j] = i;
            s1[i][p2[a[j]]]++;s2[i][a[j]]++;s3[i][a[j]]++;
            if(!rt[i][a[j]]) rt[i][a[j]] = j;
            else fa[j] = rt[i][a[j]];
        }
        rep(j,1,sizv,1) s1[i][j] += s1[i-1][j];
        rep(j,1,RV,1) s2[i][j] += s2[i-1][j];
    }
    rep(test,1,m,1){
        int op,l,r,x,y;read(op);
        if(op ^ 2) read(l,r,x,y),(x^y)?upd(l,r,x,y):void();
        else read(l,r,x),write(qry(l,r,x),'\n');
    }
}
signed main(){solve();}

标签:Ynoi2018,rt,rep,int,s2,sum,fa,未来,日记
From: https://www.cnblogs.com/hzoi-Cu/p/18544094

相关文章

  • 【日记】世界上居然有压力这么大的工作(1079 字)
    正文眼睛好疼。今晚的应酬没跑掉,毕竟是全行性质的,也跑不了。还好底层员工自动一桌,领导一桌。领导那桌各种喝酒、陪客、讲话,员工这桌就只有:“啊,这菜好咸。”或者是:“你们有谁要酸奶的?”拿过来的酸奶是常温的,不是那种粘稠的。坏耶。明天还要单独找我们柜面两个......
  • 百度世界大会2024,当应用遇上AI,未来已来
    大家好,我是小悟。各位科技爱好者小伙伴们,是不是觉得每天都在追新,却总是被新的科技热点甩在身后。就在2024年11月12日,于上海世博中心举办以“应用来了”为主题的百度世界大会2024,是一场让人眼花缭乱的科技盛宴。1、AI新篇章,让生活更“智能”这次大会上,百度展示了一系列令......
  • 大模型为什么是深度学习的未来?
    当今社会是科技的社会,是算力快速发展的时代。随着数据中心、东数西算、高性能计算、数据分析、数据挖掘的快速发展,大模型得到了快速地发展。大模型是“大算力+强算法”相结合的产物,是人工智能的发展趋势和未来。目前,大规模的生态已初具规模。其可以实现从“手工作坊”到“工......
  • 洛谷解题日记||基础篇4
     #include<iostream>usingnamespacestd;intmain(){intn,m;cin>>n>>m;//计算所有矩形的数量longlongtotalRectangles=(longlong)(n*(n+1)/2)*(longlong)(m*(m+1)/2);//计算正方形的数量longlongt......
  • 南谷的往事与未来
    纯属娱乐本人南海实验中学制作人员信息队自娱自乐在TailNightly建了个南谷一位作文大蛇就写下了一篇小说(在更新)喜剧小说,神话小说对事不对人,内容纯属虚构,切勿对号入座南谷的往事与未来洛谷网址喜剧小说,神话小说对事不对人,内容纯属虚构,切勿对号入座作者:WritingLett......
  • 德必集团携手ZLead成功举办“笑投未来·投资人大会”,聚焦全球科技创新与创业投资
    2024年11月2日,由ZLead硅谷委员会(以下简称ZLead)、中国科学院大学金融校友联合会和清华校友总会碳中和专业委员会联合主办的“笑投未来·投资人大会”在德必世纪WE成功举办。本次大会由德必集团和上海麒名吉文化传媒有限公司承办,汇聚了来自180个顶尖投资机构的200位创始合伙人、......
  • 【日记】居然把今天的应酬逃掉了(668 字)
    正文今天副行长回来了。本来以为今晚又要应酬,结果跑掉了。嘿嘿。有一个企业的董事长听说他回来了,所以嚷嚷着要请客。而客户请吃饭的对象又只有客户经理,所以我和柜面主管两个人就溜了。办公室的人也没去。不过明天是全行内部性质的,估计溜不了了。能逃一次是一次吧,嘿嘿,果......
  • 算力运力解决方案:算网融合,打造未来科技新引擎
    算力运力解决方案是一个融合算力、算商、算法、数据以及应用为一体的综合性算网生态,旨在提供广泛辐射不同行业应用的算网服务,并为客户提供多样化的算力产品套餐选择。这一解决方案不仅满足了多样化的算力需求,还通过高效的运算和处理能力,支持各种复杂的数据分析和应用需求。产品......
  • wsl2踩坑日记(配置代理/zsh+p10k/Neovim)
    1.proxywsl--installUbuntu-24.04安装好wsl之后,测试了一下v2rayN的代理能不能正常使用(用vultr服务器搭建的校园网ipv6免流),发现可以curlwww.google.com,但是sudoapt-getupdate报错Clearsignedfileisn'tvalid,got'NOSPLIT'(doesthenetworkrequireauthe......
  • 【热门主题】000040 探索 ECMAScript:从起源到未来
    前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏+关注哦......