zoukankan      html  css  js  c++  java
  • Luogu5072 [Ynoi2015]盼君勿忘 【莫队】

    题目描述:对于一个长度为(n)的序列,(m)次询问(l,r,p),计算([l,r])的所有子序列的不同数之和(mathrm{mod} p)

    数据范围:(n,m,a_ileq 10^5,pleq 10^9)

    来做做Ynoi中相对简单的题目。。。

    首先我们考虑每个数的贡献,如果它出现了(k)次,那么会在(2^{r-l+1}-2^{r-l+1-k})个子序列中出现。所以维护(s[k])表示所有出现(k)次的数之和,而且(s[k])中不为0的只有(sqrt{n})个。

    所以使用莫队,维护(s[k])并使用hash表维护(s[k])中不为0的个数,并使用光速幂预处理(2)的幂次,然后可以(O(sqrt{n}))计算了,时间复杂度(O((n+m)sqrt{n}))

    如果你就这样写了,很容易被卡常,但是根据lxl的数据,hash表可以只维护出现次数(>sqrt{n})的,然后([1,sqrt{n}])的直接遍历,这样常数就会小很多。

    #include<bits/stdc++.h>
    #define Rint register int
    using namespace std;
    typedef long long LL;
    const int N = 100003, mod = 998244353;
    inline int kasumi(int a, int b){
    	int res = 1;
    	while(b){
    		if(b & 1) res = (LL) res * a % mod;
    		a = (LL) a * a % mod; b >>= 1;
    	}
    	return res;
    }
    int n, m, inv[N], root[N << 2], val[N * 350], ls[N * 350], rs[N * 350], cnt;
    inline int Add(int a, int b){return (a + b >= mod) ? (a + b - mod) : (a + b);}
    inline int Sub(int a, int b){return (a < b) ? (a + mod - b) : (a - b);}
    inline int add(int a, int b){return Add((LL) a * Sub(1, b) % mod, (LL) b * Sub(1, a) % mod);}
    inline void change(int &x, int L, int R, int l, int r, int v){
    	if(!x) x = ++ cnt;
    	if(l <= L && R <= r){val[x] = add(val[x], v); return;}
    	int mid = L + R >> 1;
    	if(l <= mid) change(ls[x], L, mid, l, r, v);
    	if(mid < r) change(rs[x], mid + 1, R, l, r, v);
    }
    inline int query(int x, int L, int R, int p){
    	if(!x) return 0;
    	if(L == R) return val[x];
    	int mid = L + R >> 1;
    	if(p <= mid) return add(val[x], query(ls[x], L, mid, p));
    	else return add(val[x], query(rs[x], mid + 1, R, p));
    }
    inline void change(int x, int L, int R, int l1, int r1, int l2, int r2, int v){
    	if(l1 <= L && R <= r1){change(root[x], 1, n, l2, r2, v); return;}
    	int mid = L + R >> 1;
    	if(l1 <= mid) change(x << 1, L, mid, l1, r1, l2, r2, v);
    	if(mid < r1) change(x << 1 | 1, mid + 1, R, l1, r1, l2, r2, v);
    }
    inline int query(int x, int L, int R, int p1, int p2){
    	if(L == R) return query(root[x], 1, n, p2);
    	int mid = L + R >> 1;
    	if(p1 <= mid) return add(query(root[x], 1, n, p2), query(x << 1, L, mid, p1, p2));
    	else return add(query(root[x], 1, n, p2), query(x << 1 | 1, mid + 1, R, p1, p2));
    }
    int main(){
    	scanf("%d%d", &n, &m);
    	for(Rint i = 1;i <= n;i ++) inv[i] = kasumi(i, mod - 2);
    	while(m --){
    		int opt, l, r;
    		scanf("%d%d%d", &opt, &l, &r);
    		if(opt == 1){
    			if(l > 1){
    				change(root[0], 1, n, 1, l - 1, 1);
    				change(1, 1, n, 1, l - 1, l, r, inv[r - l + 1]);
    			}
    			if(r < n){
    				change(root[0], 1, n, r + 1, n, 1);
    				change(1, 1, n, l, r, r + 1, n, inv[r - l + 1]);
    			}
    			if(l < r) change(1, 1, n, l, r, l, r, 2ll * inv[r - l + 1] % mod);
    			change(root[0], 1, n, l, r, Sub(1, inv[r - l + 1]));
    		} else if(l == 1) printf("%d
    ", Sub(1, query(root[0], 1, n, r)));
    		else printf("%d
    ", Sub(1, query(1, 1, n, l - 1, r)));
    	}
    }
    
  • 相关阅读:
    MVC设置默认页面
    MySQL_DBA整理
    解决git提交敏感信息(回退git版本库到某一个commit)
    并发数计算
    高并发下的 Nginx 优化与负载均衡
    PassengerNginxdebian快速部署Rails
    Linux+postfix+extmail+dovecot打造基于web页面的邮件系统
    2018.11.30软件更新公告
    2018.10.11软件更新公告
    2018.09.25软件更新公告
  • 原文地址:https://www.cnblogs.com/AThousandMoons/p/11558994.html
Copyright © 2011-2022 走看看