zoukankan      html  css  js  c++  java
  • 「题解」Codeforces 348C Subset Sums

    默认 (n,m,q,sum |S|) 同阶。

    大小 (<sqrt n) 的称为小集合,(>sqrt n) 的称为大集合,其中大集合的个数不超过 (sqrt n) 个。

    可以提前 (mathcal{O}(nsqrt n)) 地预处理出与其他所有集合之间有多少重复的元素,开个桶就可以。

    对于每个大集合,直接记录 (w) 为集合内所有数的和,记录一个 (v) 代表 (2) 操作给这个集合加了多少。

    对于大集合的修改:(mathcal{O}(sqrt n)) 复杂度内给其他每个大集合记录下产生贡献(通过预处理已经可以 (mathcal{O}(1)) 算出 (w) 应该增长多少)。

    对于小集合的修改:给原数组对应处的位置加上数,然后也是将 (mathcal{O}(sqrt n)) 个大集合的 (w) 加上某个数。

    对于大集合的询问:大集合和小集合的修改都已经修改到了 (w) 上,所以答案就是对应的 (w)

    对于小集合的询问:首先 (mathcal{O}(sqrt n)) 遍历原数组对应处位置,能知道小集合的修改对其的贡献;然后遍历 (mathcal{O}(sqrt n)) 个大集合,根据预处理和 (v) 的记录能够 (mathcal{O}(1)) 算出大集合的修改对其的贡献。

    综上所述,复杂度为 (mathcal{O}(nsqrt n))

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    #include<unordered_map>
    #define pb emplace_back
    #define mp std::make_pair
    #define fi first
    #define se second
    typedef long long ll;
    typedef std::pair<int, int> pii;
    typedef std::pair<ll, int> pli;
    typedef std::pair<ll, ll> pll;
    typedef std::vector<int> vi;
    typedef std::vector<ll> vll;
    const ll mod = 998244353;
    ll Add(ll x, ll y) { return (x+y>=mod) ? (x+y-mod) : (x+y); }
    ll Mul(ll x, ll y) { return x * y % mod; }
    ll Mod(ll x) { return x < 0 ? (x + mod) : (x >= mod ? (x-mod) : x); }
    ll cadd(ll &x, ll y) { return x = (x+y>=mod) ? (x+y-mod) : (x+y); }
    template <typename T> T Max(T x, T y) { return x > y ? x : y; }
    template <typename T> T Min(T x, T y) { return x < y ? x : y; }
    template <typename T>
    T &read(T &r) {
    	r = 0; bool w = 0; char ch = getchar();
    	while(ch < '0' || ch > '9') w = ch == '-' ? 1 : 0, ch = getchar();
    	while(ch >= '0' && ch <= '9') r = r * 10 + (ch ^ 48), ch = getchar();
    	return r = w ? -r : r;
    }
    const int N = 100010;
    const int B = 316;
    int n, m, q;
    int siz[N];
    vi s[N];
    ll w[N], v[N], a[N];
    int vis[N], cnt[B+10][N], pos[N], rk[N], pct;
    void calc(int p) {
    	for(auto x : s[p]) vis[x] = 1, w[p] += a[x];
    	for(int i = 1; i <= m; ++i)
    		for(auto x : s[i])
    			if(vis[x])
    				++cnt[pos[p]][i];
    	for(auto x : s[p]) vis[x] = 0;
    }
    signed main() {
    	read(n); read(m); read(q);
    	for(int i = 1; i <= n; ++i) read(a[i]);
    	for(int i = 1; i <= m; ++i) {
    		read(siz[i]);
    		for(int j = 1, x; j <= siz[i]; ++j) read(x), s[i].pb(x);
    	}
    	for(int i = 1; i <= m; ++i)
    		if(siz[i] > B)
    			pos[i] = ++pct, rk[pct] = i, calc(i);
    	for(int o = 1; o <= q; ++o) {
    		char ch = getchar(); int k, x;
    		while(ch != '?' && ch != '+') ch = getchar();
    		if(ch == '+') {
    			read(k); read(x);
    			if(siz[k] > B) {
    				v[k] += x;
    				for(int i = 1; i <= pct; ++i)
    					w[rk[i]] += 1ll * cnt[i][k] * x;
    			}
    			else {
    				for(auto i : s[k]) a[i] += x;
    				for(int i = 1; i <= pct; ++i)
    					w[rk[i]] += 1ll * cnt[i][k] * x;
    			}
    		}
    		else {
    			read(k);
    			if(siz[k] > B) printf("%lld
    ", w[k]);
    			else {
    				ll ans = 0;
    				for(auto i : s[k]) ans += a[i];
    				for(int i = 1; i <= pct; ++i)
    					ans += v[rk[i]] * cnt[i][k];
    				printf("%lld
    ", ans);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    CCF-201803-3-URL映射(模拟)
    Problem UVA11134-Fabled Rooks(贪心)
    UVA1152-4 Values whose Sum is 0(分块)
    UVA1605-Building for UN(思维)
    基于XMPP的IOS聊天客户端程序(IOS端一)
    基于XMPP的IOS聊天客户端程序(XMPP服务器架构)
    正则表达式在iOS中的运用
    NSUserDefaults 简介,使用 NSUserDefaults 存储自定义对象
    自动无限循环UIScrollView原理
    NSTimeZone
  • 原文地址:https://www.cnblogs.com/do-while-true/p/15381390.html
Copyright © 2011-2022 走看看