码迷,mamicode.com
首页 > 其他好文 > 详细

【分块】CODEFORCES 384C Subset Sums

时间:2015-08-17 21:23:48      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:

通道

题意:给出n个数,m组序列,然后每次可以选择一个序列给对应的每个数加定值,及询问该组对应数之和

思路:可以知道修改某一组后,肯定对应和其他组有相交部分也要对应修改,每次去修改肯定不现实,然后对于sqrt(n)以内的数可以O(n)修改,其他的只要计算对应的增量即可,然后维护对于大于sqrt(n)的序列会影响到哪些小于sqrt(n)的序列即可。

代码:

技术分享
#include <cstdio>
#include  <cmath>
#include <vector>
using namespace std;

typedef long long ll;
const int N = 100005;
const int M = 333;

int n , m , q;
int size[N], id[N];
int bigcnt = 0, vis[N];
int inter[N][M];
ll a[N];
ll ans[N] , update[N];   
vector<int> num[N];

int main() {  
    scanf("%d%d%d" , &n , &m , &q);
    for (int i = 1 ; i <= n ; i ++) {
        scanf ("%I64d" , &a[i]);
    }
    int limit = (int)sqrt (n) + 1;
    for (int i = 1 ; i <= m ; i ++) {
        scanf ("%d" , &size[i]);
        num[i].resize(size[i]);
        for (int j = 0 ; j < size[i] ; j ++) {
            scanf ("%d" , &num[i][j]);
        }
        if (size[i] >= limit) {
            id[i] = bigcnt++;
        } else id[i] = -1;
    }
    for (int i = 1 ; i <= m ; i ++) 
        if (id[i] != -1) {
            for (int j = 0 ; j < size[i] ; j ++) {
                vis[num[i][j]] = i;
                ans[id[i]] += a[num[i][j]];
            }
            for (int j = 1 ; j <= m ; j ++) {
                for (int k = 0 ; k < size[j] ; k ++)
                    if (vis[num[j][k]] == i)
                        inter[j][id[i]]++;
            }
        }
    while (q --) {
        char str[5];int idx;
        scanf ("%s%d" , str , &idx);
        if (str[0] == ?) {
            if (id[idx] == -1) {
                ll ret = 0;
                for (int i = 0 ; i < size[idx] ; i ++)
                    ret += a[num[idx][i]];
                for (int i = 0 ; i < bigcnt ; i ++) 
                    ret += 1LL * update[i] * inter[idx][i];
                printf ("%I64d\n" , ret);
            } else printf ("%I64d\n" , ans[id[idx]]);
        } else {
            int x; scanf ("%d" , &x);
            for (int i = 0 ; i < bigcnt ; i ++) 
                ans[i] += 1LL * inter[idx][i] * x;
            if (id[idx] == -1) {
                for (int i = 0 ; i < size[idx] ; i ++)
                    a[num[idx][i]] += x;
            } else update[id[idx]] += x;
        }
    }
    return 0;
}
View Code

 

【分块】CODEFORCES 384C Subset Sums

标签:

原文地址:http://www.cnblogs.com/Rojo/p/4737596.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!