题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2375
小t非常喜爱画画,但是他还是一个初学者。他最近费尽千辛万苦才拜到已仙逝的达 芬奇为师(神仙?妖怪?谢谢)。达芬奇果然是画鸡蛋长大的,让小t一入门就拿着一张白纸条疯狂地涂色。假设纸条被划分成了n个区域,用1~n的整数从左到 右顺序编号,达芬奇总共下达了m条指令。第I条指令是让小t把编号为(I*p+q)mod n+1与(I*q+p)mod n+1(p,q为常整数)之间的区域(连续的一段区域)涂成第I种颜色。你可以假设达芬奇家中颜料的颜色数足够多(达芬奇是画鸡蛋长大的)。
现在由于达芬奇下达的指令过多,小t一时应付不过来。达芬奇只让他回答每一个区域最后的颜色。趁达芬奇还在“五谷轮回之所”忙碌时,小t偷偷的请让你这个计算机高手帮他算出最后的颜色状态,并告诉他。时间紧迫,要快哟!(达芬奇的指令次数多到恶心)
100%数据满足:1≤n≤1000000,1≤m≤10000000;1≤m*p+q,m*q+p≤231-1;
题解:考虑反着刷,从m开始刷,当前被涂上色的最后一定是该颜色。涂上色的就删去。
这让我们想到了链表,但实际上这样也有可能跳跃很多次。
最好的办法是并查集,类似与上帝造题的7分钟,我们一旦某个点 i 被涂色了,就将它合并到 i+1 所在的连通块里。
这样均摊下来复杂度是O(n)的
代码:
100%数据满足:1≤n≤1000000,1≤m≤10000000;1≤m*p+q,m*q+p≤231-1;
题解:考虑反着刷,从m开始刷,当前被涂上色的最后一定是该颜色。涂上色的就删去。
这让我们想到了链表,但实际上这样也有可能跳跃很多次。
最好的办法是并查集,类似与上帝造题的7分钟,我们一旦某个点 i 被涂色了,就将它合并到 i+1 所在的连通块里。
这样均摊下来复杂度是O(n)的
代码:
#include<cstdio> #include<cstdlib> #include<cmath> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<map> #include<set> #include<queue> #include<string> #define inf 1000000000 #define maxn 1000000+5 #define maxm 500+100 #define eps 1e-10 #define ll long long #define pa pair<int,int> #define for0(i,n) for(int i=0;i<=(n);i++) #define for1(i,n) for(int i=1;i<=(n);i++) #define for2(i,x,y) for(int i=(x);i<=(y);i++) #define for3(i,x,y) for(int i=(x);i>=(y);i--) #define mod 1000000007 using namespace std; inline int read() { int x=,f=;char ch=getchar(); while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();} while(ch>=''&&ch<=''){x=*x+ch-'';ch=getchar();} return x*f; }
int n,m,p,q,v[maxn],fa[maxn];
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);} int main() { freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); n=read();m=read();p=read();q=read();
for1(i,n+)fa[i]=i;
for3(i,m,)
{
int l=(i*p+q)%n+,r=(i*q+p)%n+;if(l>r)swap(l,r);
for(int j=find(l);j<=r;j=find(j+))
{
v[j]=i;
fa[j]=find(j+);
}
if(find()==n+)break;
}
for1(i,n)printf("%d\n",v[i]); return ; }