zoukankan      html  css  js  c++  java
  • BZOJ 1202 狡猾的商人

    Description

    刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的。账本上记录了(n)个月以来的收入情况,其中第i 个月的收入额为(A_{i}(i=1,2,3...n-1,n)) 。当(A_{i})大于(0)时表示这个月盈利(A_{i}) 元,当 (A_{i})小于(0)时表示这个月亏损(A_{i}) 元。所谓一段时间内的总收入,就是这段时间内每个月的收入额的总和。 刁姹的任务是秘密进行的,为了调查商人的账本,她只好跑到商人那里打工。她趁商人不在时去偷看账本,可是她无法将账本偷出来,每次偷看账本时她都只能看某段时间内账本上记录的收入情况,并且她只能记住这段时间内的总收入。 现在,刁姹总共偷看了(m)次账本,当然也就记住了(m)段时间内的总收入,你的任务是根据记住的这些信息来判断账本是不是假的。

    Input

    第一行为一个正整数(w),其中(w<100),表示有(w)组数据,即(w)个账本,需要你判断。每组数据的第一行为两个正整数(n)(m),其中(n<100,m<1000),分别表示对应的账本记录了多少个月的收入情况以及偷看了多少次账本。接下来的(m)行表示刁姹偷看(m)次账本后记住的(m)条信息,每条信息占一行,有三个整数(s,t)(v),表示从第(s)个月到第(t)个月(包含第(t)个月)的总收入为(v),这里假设(s)总是小于等于(t)

    Output

    包含(w)行,每行是(true)(false),其中第(i)行为(true)当且仅当第(i)组数据,即第(i)个账本不是假的;第(i)行为(false)当且仅当第(i)组数据,即第(i)个账本是假的。

    Sample Input

    2
    3 3
    1 2 10
    1 3 -5
    3 3 -15
    5 3
    1 5 100
    3 5 50
    1 2 51

    Sample Output

    true
    false

    感觉这是一道很好的题,也挺神的。数据结构用的并不高深,是众人皆知的并查集。
    首先我们知道一个账本非法当且仅当给出值与推出值不一。这道题最妙的地方就在于他可以用并查集来维护这个推出值。
    我们令(val[i])(每个集合的代表元(val)(0))表示账本的前缀和(pre[i]-pre[find(i)])的值,那么我们所需要做的就是维护这个(val)数组即可。
    首先我们将(find)函数进行修改,使之可以维护val值:

    inline int find(int a)
    {
    	if (father[a] == a) return father[a];
    	int p = find(father[a]);
    	val[a] += val[father[a]];
    	return father[a] = p;
    }
    

    之后就是我们的判断与更新。
    对于我们的询问(s,t,v)。我们首先查询(s-1)(t)是否在一个集合内部。如果在,判断(val[t]-val[s-1])是否与(v)相等(令(p=find(t)=find(s-1))(val[t]=per[t]-pre[p])(val[s-1]=pre[s-1]-pre[p])(val[t]-val[s-1]=pre[t]-pre[s-1]));否则更新答案,(val[find(s-1)]=val[t]-val[s-1]-v)(令(q=val[s-1]),因为(val[s-1]=val[t]-v),且(val[s-1]-q=val[find(s-1)]),所以有(val[find(s-1)]=val[t]-q-c=val[t]-val[s-1]-v))。
    于是这段代码也就出来了:

    inline bool work(int a,int b,int c)
    {
    	int p = find(a),q = find(b);
    	if (p == q) if (val[b] - val[a] != c) return false;
    	val[p] = val[p] + val[b] - val[a] - c;     //维护前缀和
    	father[p] = q;
    	return true;
    }
    
    

    整合起来,贴一份完整的:

    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    
    #define maxn 110
    int n,m,father[maxn],val[maxn];
    
    inline void init() { for (int i = 0;i <= n;++i) val[i] = 0,father[i] = i; }
    
    inline int find(int a)
    {
    	if (father[a] == a) return father[a];
    	int p = find(father[a]);
    	val[a] += val[father[a]];
    	return father[a] = p;
    }
    
    inline bool work(int a,int b,int c)
    {
    	int p = find(a),q = find(b);
    	if (p == q) if (val[b] - val[a] != c) return false;
    	val[p] = val[p] + val[b] - val[a] - c;  
    	father[p] = q;
    	return true;
    }
    
    int main()
    {
    	freopen("1202.in","r",stdin);
    	freopen("1202.out","w",stdout);
    	int T,i,a,b,c;
    	scanf("%d",&T);
    	while (T--)
    	{
    		scanf("%d %d",&n,&m);
    		init();
    		for (i = 1;i <= m;++i)
    		{
    			scanf("%d %d %d",&a,&b,&c);
    			if (!work(a-1,b,c)) { printf("false
    "); break; }
    		}
    		if (i == m + 1) printf("true
    ");
    	}
    	fclose(stdout); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    el-select下拉框选项太多导致卡顿,使用下拉框分页来解决
    vue+elementui前端添加数字千位分割
    Failed to check/redeclare auto-delete queue(s)
    周末啦,做几道面试题放松放松吧!
    idea快捷键
    解决flink运行过程中报错Could not allocate enough slots within timeout of 300000 ms to run the job. Please make sure that the cluster has enough resources.
    用.net平台实现websocket server
    MQTT实战3
    Oracle 查看当前用户下库里所有的表、存储过程、触发器、视图
    idea从svn拉取项目不识别svn
  • 原文地址:https://www.cnblogs.com/mmlz/p/4320207.html
Copyright © 2011-2022 走看看