「NOIP模拟赛」染色问题
「题目描述」
平面上有n个珠子排成一排, 每个珠子初始颜色为0,你要对他们进行m次染色,每次你选定l和r,然后把[l,r]之间的珠子染成编号c的颜色,每个珠子的最终颜色为它曾经染过的编号最大的颜色,请你写个程序统计每个珠子最终的颜色。
「输入格式」
第一行两个数n,m,表示珠子个数和染色的次数
接下来m行,每行三个数l,r,c如题意所示
「输出格式」
由于数据较大,为了减少输出所用的不必要的时间,请采取以下方法输出:
假如a[i]为第i个珠子的最终颜色
ans := 0;
for i := 1 to n do ans := (ans * 1200007 + a[i]) mod 999911659;
writeln(ans);
注意用int64保存相关变量,防止运算过程中越界
「样例输入」
3 2
1 2 1
2 2 2
「样例输出」
146411103
「数据范围」
30% n,m<=5000
50% n,m <= 10000
80% n,m <= 500000
100% n <= 1000000, m <= 2000000
「时间限制」
2s
题解
线段树不知道有多少,但是有更为简单的做法
用to[i]表示i结点后第一个未被染色的结点编号,将操作按C排序后从大到小操作,顺便更新to数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> #define inf 1000000000 #define ll long long using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n,m,to[1000005]; ll a[1000005],ans; struct data{int l,r;ll c;}b[2000005]; void solve(int l,int r,ll c) { int t; for(int i=l;i<=r;i=t) { t=to[i]; if(!a[i])a[i]=c; to[i]=max(to[i],r+1); } } bool operator<(data a,data b) { return a.c>b.c; } int main() { //freopen("color.in","r",stdin); //freopen("color.out","w",stdout); n=read();m=read(); for(int i=1;i<=n;i++)to[i]=i+1; for(int i=1;i<=m;i++) { b[i].l=read();b[i].r=read();b[i].c=read(); } sort(b+1,b+m+1); for(int i=1;i<=m;i++) solve(b[i].l,b[i].r,b[i].c); for(int i=1;i<=n;i++) ans=(ans*1200007+a[i])%999911659; printf("%I64d",ans); return 0; } |
Subscribe