2020牛客寒假算法基础集训营4 H题

坐火车

题目描述

牛牛是一名喜欢旅游的同学,在来到渡渡鸟王国时,坐上了颜色多样的火车。
牛牛同学在车上,车上有 n 个车厢,每一个车厢有一种颜色。
他想知道对于每一个正整数x∈[1, n] ,集合{(i, x, j) ∣ i<x<j, l x≤col i=col j≤rx}中包含多少个元素。
换句话说,就是要求每一个车厢两边有多少对颜色相同的车厢,并且这一对车厢的颜色要在 lx 到 rx 之间。其中 coli 代表 i 号车厢的颜色,lx,rx 代表颜色的限制。

输入描述:

第一行一个正整数n。
第二行 n 个三元组,每个三元组包括三个正整数 (coli, li, ri),输入中没有括号,这 3n 个正整数之间均只用空格隔开,详见样例。

输出描述:

输出一行 n 个非负整数代表答案。


这道题思维比较难想;

解释一下题解代码:

思考的对象可以放在每次枚举的车厢的颜色上,从1–n枚举每个车厢,当前车厢的颜色为x,这个位置的车厢就不能与前面的车厢颜色为x的匹配,所有我们要减去当前位置 i 前面x的个数(因为我们之前就已经加上),还要加上当前位置 i 后面的 x 的个数(意味着这个位置 i 可以和他们匹配);

所以树状数组就是一个不错的选择;

#include<bits/stdc++.h>
#define ll long long
#define pa pair<int,int>
#define lson k<<1
#define rson k<<1|1
//ios::sync_with_stdio(false);
using namespace std;
const int N=500100;
const int M=200100;
const ll mod=998244353;
ll s1[N],s2[N],tr[N];//s1代表数i的后面还有几个数i,s2代表数i前面还有几个数i 
int n;
struct Node{
	int l,r,c;
}col[N];
int lowbit(int k){
	return k & (-k);
}
void add(int p,ll q){//p点加上q,单点修改 
	while(p<=N){
		tr[p]+=q;
		p+=lowbit(p);
	}
}
ll sum(int p){//单点查询,就是求前缀和 
	ll s=0;
	while(p!=0){
		s+=tr[p];
		p-=lowbit(p);
	}
	return s;
}
int main(){
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++) cin>>col[i].c>>col[i].l>>col[i].r;
    for(int i=n;i>=1;i--) s1[col[i].c]++;
    for(int i=1;i<=n;i++){
    	s1[col[i].c]--;//后面还有几个col[i].c 
    	add(col[i].c,-s2[col[i].c]);//减去前面col[i].c的个数 
    	cout<<sum(col[i].r)-sum(col[i].l-1)<<" ";
    	s2[col[i].c]++;//前面还有几个col[i].c
    	add(col[i].c,s1[col[i].c]); 
	} 
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值