zoukankan      html  css  js  c++  java
  • 题解 P5072 【[Ynoi2015] 盼君勿忘】

    简化题面

    珂朵莉给了你一个序列,每次查询一个区间([l,r])中所有子序列分别去重后的和(mod p)

    (1 le n,m,a_i le 10^5,1le p le 10^9,1le l le r le n)

    解题思路

    最简单的一道(Ynoi)

    考虑如果一个数(x)在区间([l,r])出现了(k)次,那么显然会出现在长度为(r-l+1-k)的所有集合内,那么产生贡献的总集合个数为(2^{r-l+1}-2^{r-l+1-k})

    考虑如何统计区间内每个数出现的个数,显然(HH)的项链啊= =

    直接暴力上莫队,用(stl)自带的(unordered set)来维护

    考虑维护每个数的个数(cnt),维护个数为(x)个的数的和(sum)

    在转移区间的时候如果是添加贡献,那么先将原来这个位置的数的个数对(sum)的贡献减去,如果为(0)了就删掉,然后增加(cnt)后的(sum)添加到(set)内,减的话同理,具体实现看代码。
    如果加上个快速幂时间复杂度显然为(O(nsqrt{m} logn))(T)

    直接上光速幂即可,然后如果自己闲的没事的话也可以拿个链表之类的数据结构维护一下个数也行,普通莫队排序还是会(T),这里代码用的是奇偶优化后的莫队排序

    (mathcal{Code})

    // Author: Ame__
    #include<bits/stdc++.h>
    #define _ 0
    #define qwq double
    #define AME__DEBUG
    #define LL long long
    #define bomb exit(0)
    #define LOG(FMT...) fprintf(stderr , FMT)
    #define TOWA(FMT...) fprintf(stdout , FMT)
    using namespace std;
    /*Grievous Lady*/
        
    const int BUF_SIZE = 1 << 12;
        
    char buf[BUF_SIZE] , *buf_s = buf , *buf_t = buf + 1;
        
    #define PTR_NEXT() 
    { 
        buf_s ++; 
        if(buf_s == buf_t) 
        { 
            buf_s = buf; 
            buf_t = buf + fread(buf , 1 , BUF_SIZE , stdin); 
        } 
    }
        
    #define mians(_s_) 
    { 
        while(!isgraph(*buf_s)) PTR_NEXT();
        char register *_ptr_ = (_s_); 
        while(isgraph(*buf_s) || *buf_s == '-') 
        { 
            *(_ptr_ ++) = *buf_s; 
            PTR_NEXT(); 
        } 
        (*_ptr_) = ''; 
    }
        
    template <typename _n_> void mian(_n_ & _x_){
        while(*buf_s != '-' && !isdigit(*buf_s)) PTR_NEXT();
        bool register _nega_ = false; if(*buf_s == '-'){ _nega_ = true; PTR_NEXT(); }
        _x_ = 0; while(isdigit(*buf_s)){ _x_ = _x_ * 10 + *buf_s - '0'; PTR_NEXT(); } if(_nega_) _x_ = -_x_;
    }
    
    const int kato = 1e5 + 10;
    
    template <typename _n_> bool cmax(_n_ &a , const _n_ &b){ return a < b ? a = b , 1 : 0; }
        
    template <typename _n_> bool cmin(_n_ &a , const _n_ &b){ return a > b ? a = b , 1 : 0; }
        
    int n , m , bol;
    LL a[kato] , cnt[kato] , sum[kato] , ans[kato];
    unordered_set<int> deco;
    
    class quick_quick_pow{
        private:
            LL res1[kato] , res2[kato]; int N;
        public:
            inline void get_ans(int mod){ 
                res1[0] = res2[0] = 1; 
                for(int i = 1;i <= bol;i ++) res1[i] = 1LL * res1[i - 1] * 2 % mod; 
                for(int i = 1;i <= bol;i ++) res2[i] = 1LL * res2[i - 1] * res1[bol] % mod;
            }
        
            inline LL qaq(int x , int mod){ return 1LL * res1[x % bol] * res2[x / bol] % mod; }    
    }towa;
        
    struct node{
        int l , r , id , mod;
        
        friend bool operator <(const node &a , const node &b){
            return (a.l / bol ^ b.l / bol) ? a.l / bol < b.l / bol : (a.l / bol & 1) ? a.r < b.r : a.r > b.r;
        }
    }e[kato];
        
    inline void add(int x){
        if(cnt[a[x]]){
            sum[cnt[a[x]]] -= a[x];
            if(!sum[cnt[a[x]]]) deco.erase(cnt[a[x]]);
        }
        cnt[a[x]] ++;
        if(!sum[cnt[a[x]]]) deco.insert(cnt[a[x]]);
        sum[cnt[a[x]]] += a[x];
    }
        
    inline void del(int x){
        sum[cnt[a[x]]] -= a[x];
        if(!sum[cnt[a[x]]]) deco.erase(cnt[a[x]]);
        cnt[a[x]] --;
        if(cnt[a[x]]){
            if(!sum[cnt[a[x]]]) deco.insert(cnt[a[x]]);
            sum[cnt[a[x]]] += a[x];
        }
    }
        
    inline int get_sum(int l , int r , int mod){
        LL res = 0 , tot = towa.qaq(r - l + 1 , mod);
        for(auto it = deco.begin(); it != deco.end(); it ++) res = (res + sum[*it] * (tot - towa.qaq(r - l + 1 - *it , mod) + mod) % mod) % mod;
        return res % mod;
    }
        
    inline int Ame_(){
    #ifdef AME__
        freopen(".in" , "r" , stdin); freopen(".out" , "w" , stdout); int nol_cl = clock();
    #endif
        mian(n) , mian(m); bol = sqrt(m);
        for(int i = 1;i <= n;i ++) mian(a[i]);
        for(int i = 1;i <= m;i ++){
            mian(e[i].l) , mian(e[i].r) , mian(e[i].mod);
            e[i].id = i;
        }
        sort(e + 1 , e + 1 + m);
        int l = e[1].l , r = l - 1;
        for(int i = 1;i <= m;i ++){
            while(l > e[i].l) add(-- l);
            while(r < e[i].r) add(++ r);
            while(l < e[i].l) del(l ++);
            while(r > e[i].r) del(r --);
            towa.get_ans(e[i].mod);
            ans[e[i].id] = get_sum(e[i].l , e[i].r , e[i].mod);
        }
        for(int i = 1;i <= m;i ++) TOWA("%lld
    " , ans[i]);
    #ifdef AME__TIME
        LOG("Time: %dms
    ", int((clock() - nol_cl) / (qwq)CLOCKS_PER_SEC * 1000));
    #endif
        return ~~(0^_^0); /*さようならプログラム*/
    }
        
    int Ame__ = Ame_();
        
    int main(){;}
    
    /*
    4 2
    1 7
    6 8
    7 10
    9 13
    */
    
    呐,这份感情,什么时候可以传达呢
  • 相关阅读:
    c#动态类型
    [转]鼠标和键盘模拟API
    c#各类型转byte[]或转回
    Unity3D发布安卓报错permisson denied的解决
    NuGet修改packages目录/迁移缓存文件夹
    数据结构:单向链表系列7--交换相邻两个节点2(交换链域/指针域)
    数据结构:单向链表系列6--交换相邻两个节点1(交换数据域)
    数据结构:单向链表系列5--在链表中查找元素
    数据结构:单向链表系列4--获取链表长度(迭代法和递归法)
    数据结构:单向链表系列3--删除节点
  • 原文地址:https://www.cnblogs.com/Ame-sora/p/14386343.html
Copyright © 2011-2022 走看看