ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

seq题解

2022-05-22 19:01:22  阅读:157  来源: 互联网

标签:right seq int 题解 询问 fa maxn left


题解

题意

有一个长度为 \(n\) 的序列,数列中每个数都是 $ \left[ 0,p-1 \right] $ 之间的整数。

给定\(m\)个询问表示区间\(\left[l,r\right]\)之间所有数的和对\(p\)取模的结果。

求最多能满足前几次询问。

思路

先不想区间的问题,考虑如果\(x\)和\(y\)都是\(p\)的倍数,那么显然\(x+y\)也是\(p\)的倍数。

那我们对于这样具有传递性的关系,自然就可以想到带权并查集,首先我们先看一下这道题, [CEOI1999]Parity Game

相必现在大家应该有想法了吧:首先对于询问的一个区间\(\left[l,r\right]\)和一个\(k\),用\(S[i]\),表示1到\(i\)的前缀和,那么对于每次询问就是$ S[r]-S[l-1] \equiv k \pmod{p} $,然后我们就可以将每个节点的权值表示为与父亲节点对应的 \(k\) 。

然后判断:

  • 如果对于\(l-1\)和\(r\) 在同一个集合,则判断是否符合关系\(d[r]-d[l-1] \equiv k \pmod{p}\);

  • 如果不在则,合并将\(d[f[l-1]]\)设为\(d[r]-d[l-1]+k\).

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int n,m,p,fa[maxn],d[maxn],ans=-1;
int Find(int x)
{
    if(x==fa[x])return x;
    int father=Find(fa[x]);
    d[x]+=d[fa[x]];
    return fa[x]=father;
}
int main()
{
    scanf("%d%d%d",&n,&m,&p);
    for(int i=1;i<=n;i++)fa[i]=i;
    for(int i=1;i<=m;i++)
    {
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        l--;
        if(ans!=-1)continue;
        int f1=Find(l),f2=Find(r);
        if(f1!=f2)
        {
            fa[f1]=f2;
            d[f1]=d[r]-d[l]+k;
        }
        else
        {
            if((d[r]-d[l]+p)%p!=k)
            {
                ans=i-1;continue;
            }
        }
    }
    if(ans==-1)ans=m;
    printf("%d",ans);
    return 0;
}

如果不太懂的话去看我\(blog\)就好了(绝不是在推销blog)。

标签:right,seq,int,题解,询问,fa,maxn,left
来源: https://www.cnblogs.com/Jekyll-Y/p/16298617.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有