//*下午打得脑子连着眼睛一起疼
很多很基础的题目都没有做出来,规律题也找得很慢。比如下面这题,一定要多做,下次看到就直接写。
原题链接:https://codeforces.com/group/w6iGs8kreW/contest/555584/problem/C
C. Colorful Segments 2
time limit per test
2 seconds
memory limit per test
1024 megabytes
Consider nn segments on the number axis, where the left endpoint of the ii-th segment is lili and the right endpoint is riri. You need to paint each segment into one of the kk colors, so that for any two segments with the same color they do not overlap.
Calculate the number of ways to color the segments.
We say segment ii overlaps with segment jj, if there exists a real number xx satisfying both li≤x≤rili≤x≤ri and lj≤x≤rjlj≤x≤rj.
We say two ways of coloring the segments are different, if there exists one segment which has different colors in the two ways.
Input
There are multiple test cases. The first line of the input contains an integer TT indicating the number of test cases. For each test case:
The first line contains two integers nn and kk (1≤n≤5×1051≤n≤5×105, 1≤k≤1091≤k≤109) indicating the number of segments and the number of colors.
For the following nn lines, the ii-th line contains two integers lili and riri (1≤li≤ri≤1091≤li≤ri≤109) indicating the left and right endpoints of the ii-th segment.
It's guaranteed that the sum of nn of all test cases will not exceed 5×1055×105.
Output
For each test case output one line containing one integer indicating the answer. As the answer might be large, output it modulo 998244353998244353.
大致题意 : 一共给k个颜色,有n个区间。规定两个重叠区间不能染相同颜色。问有多少种染色方法。 其实想很好想,就是 排序 遍历考虑出每个区间的颜色种数(只受其前面区间的限制) 乘法原理相乘 即可。
WA:一开始是把每个点的右端点排序,然后数这个区间与前面多少区间有重叠,如果与m个重叠,那可填颜色数就是k-m。但是!这样不对,例如:
(搞笑啊)
一号和二号都能填k种,但三号不止能填k-2种(当1 2填的颜色一样时,3能填k-1种)。
so右端点排序不对!
正解:左端点排序,可以用一个优先队列来储存,每段的初始颜色都是k-1(与上段不同),如果与上段没有重合,k++。否则break。
看代码:
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
#define int long long
int t;
int n,k;
const int mod=998244353;
struct O{
int l,r;
}a[1000010];
vector<int>q;
bool sorrt(struct O i,struct O j){
return i.l<j.l;
}
void solve(int n,int k){
priority_queue<int,vector<int>,greater<int>>q;
for(int i=1;i<=n;i++){
cin>>a[i].l>>a[i].r;
}
sort(a+1,a+n+1,sorrt);
int ans=k%mod;
k--;
q.push(a[1].r);
for(int i=2;i<=n;i++){
while(!q.empty()&&q.top()<a[i].l){
k++;
q.pop();
}
ans=(ans*k)%mod;
k--;
if(k<0)k=0;
q.push(a[i].r);
}
cout<<ans<<endl;
}
signed main()
{
cin>>t;
while(t--){
cin>>n>>k;
solve(n,k);
}
return 0;
}