Codeforces Round #826 (Div. 3)

题目链接

Codeforces Round #826 (Div. 3)

F.Multi-Colored Segments

Multi-Colored Segments

题面翻译

给定一维数轴上 \(n\) 条线段,每条线段都有给定的颜色 \(c_i\)

对于每个 \(i\),请求出:

\[\min_{c_j\ne c_i}dis(i,j) \]

其中 \(dis(i,j)\) 表示线段 \(i,j\) 之间的距离,特别地,有相交(包括端点)的两条线段之间的距离定义为 \(0\)

\(T\) 组询问,\(\sum n \leq 2\times 10^5\),线段两端点 \(1\leq l,r \leq 10^9,1\leq c\leq n\)

样例 #1

样例输入 #1

9
3
1 2 1
3 4 1
5 6 2
2
100000000 200000000 1
900000000 1000000000 2
5
1 2 1
2 3 2
3 4 3
4 5 4
5 6 5
5
1 5 1
4 9 2
1 2 1
8 9 2
5 7 3
2
1 100 2
10 90 1
3
1 1 1
10 10 2
1000000000 1000000000 3
3
3 4 1
2 5 1
1 6 2
6
5 6 2
11 12 3
7 8 2
3 4 2
1 2 1
9 10 2
2
1 3 1
2 3 2

样例输出 #1

3 1 1 
700000000 700000000 
0 0 0 0 0 
0 0 2 1 0 
0 0 
9 9 999999990 
0 0 0 
3 1 3 1 1 1 
0 0

样例 #2

样例输入 #2

4
8
11 16 7
12 15 7
2 5 8
17 22 5
1 8 8
19 23 8
16 16 6
6 7 5
9
1 4 3
5 11 1
8 11 3
1 10 1
2 11 1
1 10 4
3 11 1
5 7 1
1 11 1
9
25 25 1
26 26 1
24 24 2
13 14 2
12 16 2
17 18 1
19 19 1
24 27 2
24 27 1
9
15 18 1
20 22 2
13 22 2
13 22 2
3 13 2
6 10 2
3 6 2
19 24 2
22 24 2

样例输出 #2

0 1 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 
0 0 0 3 1 1 3 0 0 
0 2 0 0 2 5 9 1 4

解题思路

线段树,二分

对于每条线段来分析,总共三种情况:与其他线段相交、左端点与其他线段右端点最近、右端点与其他线段左端点最近,对于后面两种情况,可以先将所有线段的左右端点分别放入 multiset 中,然后每次查询前先将所有颜色相等的点删除再二分即可,对于第一种情况,同理,先将所有线段端点内的区间加一,然后查询某种颜色时再将该颜色所有相关区间减一,在查询对应区间总和,和大于 \(0\) 说明有交集

  • 时间复杂度:\(O(nlogn)\)

代码

// Problem: F. Multi-Colored Segments
// Contest: Codeforces - Codeforces Round #826 (Div. 3)
// URL: https://codeforces.com/contest/1741/problem/F
// Memory Limit: 256 MB
// Time Limit: 3000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

// %%%Skyqwq
#include <bits/stdc++.h>
 
// #define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
 
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
 
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
 
template <typename T> void inline read(T &x) {
    int f = 1; x = 0; char s = getchar();
    while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
    x *= f;
}

const int N=2e5+5,inf=0x3f3f3f3f;
int t,n,res[N];
struct A
{
	int l,r,c,id;
}a[N];
struct Tr
{
	int l,r,add,sum;
}tr[N<<3];
vector<A> b[N];
vector<int> xs;
int find(int x)
{
	return lower_bound(xs.begin(),xs.end(),x)-xs.begin()+1;
}
void pushup(int p)
{
	tr[p].sum=tr[p<<1].sum+tr[p<<1|1].sum;
}
void pushdown(int p)
{
	if(tr[p].add)
	{
		tr[p<<1].sum+=tr[p].add*(tr[p<<1].r-tr[p<<1].l+1);
		tr[p<<1|1].sum+=tr[p].add*(tr[p<<1|1].r-tr[p<<1|1].l+1);
		tr[p<<1].add+=tr[p].add,tr[p<<1|1].add+=tr[p].add;
		tr[p].add=0;
	}
}
void build(int p,int l,int r)
{
	tr[p]={l,r,0,0};
	if(l==r)return ;
	int mid=l+r>>1;
	build(p<<1,l,mid),build(p<<1|1,mid+1,r);
	pushup(p);
}
void add(int p,int l,int r,int x)
{
	if(l<=tr[p].l&&tr[p].r<=r)
	{
		tr[p].sum+=x*(tr[p].r-tr[p].l+1);
		tr[p].add+=x;
		return ;
	}
	pushdown(p);
	int mid=tr[p].l+tr[p].r>>1;
	if(l<=mid)add(p<<1,l,r,x);
	if(r>mid)add(p<<1|1,l,r,x);
	pushup(p);
}
int ask(int p,int l,int r)
{
	if(l<=tr[p].l&&tr[p].r<=r)return tr[p].sum;
	pushdown(p);
	int mid=tr[p].l+tr[p].r>>1,res=0;
	if(l<=mid)res+=ask(p<<1,l,r);
	if(r>mid)res+=ask(p<<1|1,l,r);
	return res;
}
int main()
{
    for(cin>>t;t;t--)
    {
    	cin>>n;
    	xs.clear();
    	for(int i=1;i<=n;i++)
    	{
    		cin>>a[i].l>>a[i].r>>a[i].c;
    		xs.pb(a[i].l),xs.pb(a[i].r);
    		a[i].id=i;
    		b[i].clear(),res[i]=inf;
    	}
    	sort(xs.begin(),xs.end());
    	xs.erase(unique(xs.begin(),xs.end()),xs.end());
    	build(1,1,xs.size());
    	multiset<int> s[2];
    	for(int i=1;i<=n;i++)
    	{
    		a[i].l=find(a[i].l),a[i].r=find(a[i].r);
    		s[0].insert(a[i].l),s[1].insert(a[i].r);
    		b[a[i].c].pb(a[i]);
    		add(1,a[i].l,a[i].r,1);
    	}
    	for(int i=1;i<=n;i++)
    	{
    		for(auto j:b[i])
    		{
    			int l=j.l,r=j.r;
    			add(1,l,r,-1);
    			s[0].erase(s[0].lower_bound(l)),s[1].erase(s[1].lower_bound(r));
    		}
    		for(auto j:b[i])
    		{
    			int l=j.l,r=j.r,id=j.id;
    			if(ask(1,l,r))res[id]=0;
    			else
    			{
    				auto it=s[0].lower_bound(r);
    				if(it!=s[0].end())
    					res[id]=min(res[id],xs[*it-1]-xs[r-1]);
    				it=s[1].upper_bound(l);
    				if(it!=s[1].begin()&&s[1].size())
    				{
    					it--;
    					res[id]=min(res[id],xs[l-1]-xs[*it-1]);
    				}
    			}
    		}
    		for(auto j:b[i])
    		{
    			int l=j.l,r=j.r;
    			add(1,l,r,1);
    			s[0].insert(l),s[1].insert(r);
    		}
    	}
    	for(int i=1;i<=n;i++)cout<<res[i]<<' ';
    	puts("");
    }
    return 0;
}
posted @ 2022-10-31 10:01  zyy2001  阅读(35)  评论(0编辑  收藏  举报