zoukankan      html  css  js  c++  java
  • 【uoj#46】 [清华集训2014] 玄学

      题目传送门:uoj46

      题意简述:要求在序列上维护一个操作间支持结合律的区间操作,查询连续一段时间内的操作对单点的作用效果,(n leq 10^5,m leq 6 imes 10^5)

      刚开始看到这道题的时候想到树套树,然而需要用到的空间太大,时间复杂度无法承受,再一看有8s的时限,就试着强行对操作分块,看看能不能(O(m sqrt m))卡过去,不过极限数据下再怎么优化也要10s,卡不过去。

      正解可以用二进制分组的思想,对操作序列维护一棵线段树,每个结点维护子树内的操作对序列每个元素的影响(相邻两个元素的影响相同合并成一个区间表示)。然而不同于普通线段树的是,该线段树仅在左右儿子都塞满操作的时候才更新父节点的信息,这样每个结点只会被更新一次。在更新父节点的时候,可以归并地把左右儿子的信息叠加,可以证明这样的修改复杂度均摊是(O(mlog m))的。查询时可以把查询的时间区间分割到线段树的(log m)个结点上,然后在在这些结点上二分查找待查询点的操作效果。总时间复杂度(O(mlog^2m)),但实际上常数较小,能很快通过极限数据。

      代码:

    uoj46 ```cpp #include #include #include #include #include #include #define ll long long #define inf 0x3f3f3f3f #define maxn 100010 #define maxm 600010 inline ll read() { ll x=0; char c=getchar(),f=1; for(;c<'0'||'9'seq; int full; }sgt[4*maxm]; void merge(std::vector&a,std::vector&b,std::vector&ret) { int sza=a.size(),szb=b.size(),pa=0,pb=0; a.push_back((Data){n+1,n+1,one}); b.push_back((Data){n+1,n+1,one}); ret.clear(); while(pa1)sgt[now].seq.push_back((Data){1,x-1,one}); sgt[now].seq.push_back((Data){x,y,k}); if(y>1; if(!sgt[now<<1].full)add(now<<1,l,mid,x,y,k); else add(now<<1|1,mid+1,r,x,y,k); sgt[now].full=sgt[now<<1].full&sgt[now<<1|1].full; if(sgt[now].full)merge(sgt[now<<1].seq,sgt[now<<1|1].seq,sgt[now].seq); } } Opt find(std::vector&a,int pos) { int l=0,r=a.size()-1; while(l>1; if(a[mid].r>1; Opt cur=one; if(x<=mid)cur=cur*query(now<<1,l,mid,x,y,pos); if(mid
  • 相关阅读:
    TP中模型实例化
    PHP中面向对象编程思想的3个特征
    static关键字的新用法
    PHP中与类有关的运算符
    PHP中与类和对象有关的几个系统函数
    PHP中与类有关的几个魔术常量
    PHP与类有关的几个魔术方法
    PHP中类型约束
    PHP对象类型转换
    ubuntu MySQL拒绝远程连接(10061)
  • 原文地址:https://www.cnblogs.com/quzhizhou/p/11738317.html
Copyright © 2011-2022 走看看