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

HDU 3038 How Many Answers Are Wrong

时间:2015-02-01 21:48:39      阅读:286      评论:0      收藏:0      [点我收藏+]

标签:

http://acm.hdu.edu.cn/showproblem.php?pid=3038

 

题意:

给定数字个数N(A1,...,AN)和M句话,"l r s"代表下标[l,r]的数字之和为s

求出现冲突的句子数量

 

解法:

带权并查集

以区间右端为父节点,将l-1与r点合并

查询时进行路径压缩 sum[x] += sum[fa[x]]

合并时更新根节点的 sum[x] = sum[r] - sum[l] + s

则sum[x]表示[x+1, fa[x]]数字之和 (fa[x]<x时,sum[x]等于负的[A(fa[x]+1), Ax]数字之和)

同时判断同根节点的sum[l] - sum[r]是否等于给出的s

 

代码:  62MS  2236K

#include <cstdio>
using namespace std;

#define N 200001

int fa[N], sum[N], ans;

void init(int n) {
    ans = 0;
    for (int i = 0; i <= n; i++) {
        fa[i] = i;
        sum[i] = 0;
    }
}

int findfa(int n) {
    if (n == fa[n]) {
        return n;
    }
    int t = findfa(fa[n]);
    sum[n] += sum[fa[n]];
    return fa[n] = t;
}

bool unite(int l, int r, int s) {
    int x = findfa(l), y = findfa(r);
    if (x == y) {
        return (sum[l] - sum[r] != s);
    }
    fa[x] = y;
    sum[x] = sum[r] - sum[l] + s;
    return 0;
}

int main() {
    int n, q, l, r, s;
    while (~scanf("%d%d", &n, &q)) {
        init(n);
        for (int i = 0; i < q; i++) {
            scanf("%d%d%d", &l, &r, &s);
            ans += unite(l - 1, r, s);
        }
        printf("%d\n", ans);
    }
    return 0;
}

 

HDU 3038 How Many Answers Are Wrong

标签:

原文地址:http://www.cnblogs.com/rsola/p/4266029.html

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