Codeforces Round 918 (Div. 4)

A. Odd One Out

#include
#define endl '\n'
#define int long long
using namespace std;
void solve() {
	int a,b,c;
	cin>>a>>b>>c;
	map<int,int>mp;
	mp[a]++;
	mp[b]++;
	mp[c]++;
	for(auto v:mp){
		if(v.second==1){
			cout<<v.first<<endl;
			return;
		}
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

B. Not Quite Latin Square

#include
#define endl '\n'
#define int long long
using namespace std;
void solve() {
	map<char,int>mp;
	for(int i=0;i<9;i++){
		char ch;
		cin>>ch;
		mp[ch]++;
	}
	for(auto v:mp){
		if(v.second==2){
			cout<<v.first<<endl;
			return;
		}
	}
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

C. Can I Square?

#include
#define endl '\n'
#define int long long
using namespace std;
int n;
void solve() {
	cin>>n;
	int sum=0;
	for(int i=1;i<=n;i++){
		int x;
		cin>>x;
		sum+=x;
	}
	if((int)sqrt(sum)*(int)sqrt(sum)==sum) cout<<"Yes"<<endl;
	else cout<<"No"<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

D. Unnatural Language Processing
长度为n的字符串(均为小写字母a,b,c,d,e)
将单词拆分成音节

CV.CVC.CVC

#include
#define endl '\n'
#define int long long
using namespace std;
int n;
string s;
void solve() {
	cin>>n;
	cin>>s;
	map<char,int>mp1,mp2;
	mp1['a']=1;
	mp1['e']=1;
	mp2['b']=1;
	mp2['c']=1;
	mp2['d']=1;
	for(int i=0;i<n;i++){
		cout<<s[i];
		if(mp1[s[i]]==1&&mp2[s[i+1]]==1&&mp1[s[i+2]]==1) cout<<'.';
		else if(mp2[s[i]]==1&&mp2[s[i+1]]==1) cout<<'.';
	}
	cout<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

E. Romantic Glasses
一共有n个杯子
ai表示第i个杯子装了多少果汁

问能否使得[l,r]中奇数位总量和偶数位总量相同

两者总量相同,利用奇数位加,偶数位减,看是否有为0的区间

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int a[N];
int n;
void solve() {
	cin>>n;
	map<int,int>mp;
	for(int i=1;i<=n;i++) cin>>a[i];
	int sum=0;
	for(int i=1;i<=n;i++){
		if(i%2==1) sum+=a[i];
		else sum-=a[i];
		if(sum==0||mp[sum]==1){
			cout<<"Yes"<<endl;
			return;
		}
		mp[sum]=1;
	}
	cout<<"No"<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

F. Greetings
一共有n个人
ai代表第i个人的起始位置,bi代表第i个人的结束位置(所有a,b数组的数均不同)
ai小于bi

均匀速
不存在追的上,只有它的终点大于(不存在等于)另一个时,才会相遇
通过手玩发现,包含和被包含关系才会相遇一次

trick:

这就作为一个案例,当遇到统区间包含的问题时,可以有以下几种方法

枚举左端点(从小到大),一边枚举,一边把枚举过的区间的右端点放到set里,看有几个右端点是大于当前右端点的(利用set的二分upperbound),就是有几个区间包含它,就打几次招呼,set中自带的二分函数时间复杂度为O(logn),这样总的时间复杂度是O(nlogn),照理说,这样是没问题的,但是有一个问题就是set自带的二分函数返回的是迭代器,然后想要获得位置的话需要distance(迭代器1,迭代器2),它底层实现是遍历,也就是O(n),这样时间复杂度就超了,试了一下直接用迭代器减s.begin()是会报错的,这个方法就不能用了

#include
#define endl '\n'
//#define int long long
using namespace std;
const int N=2e5+10;
int l[N],r[N];
int n;
struct node{
	int l,r;
	bool operator<(const node &W)const{
		return l<W.l;
	}
}q[N];
void solve() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>q[i].l>>q[i].r;
	sort(q+1,q+1+n);
	set<int>s;
	int ans=0;
	s.insert(q[1].r);
	for(int i=2;i<=n;i++){
		auto t=s.upper_bound(q[i].r);
		int d=distance(s.begin(),t);
		ans+=s.size()-d;
		s.insert(q[i].r);
	}
	cout<<ans<<endl;
}
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

于是改用树状数组,但是有一个问题就是数的范围太大了,达到了1e9,要想用树状数组的话,这些数值本身作为一个位置,空间肯定爆了,所幸数的个数比较小,于是先离散化,这样的话空间就不会爆了

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int l[N],r[N];
int tr[N];
int n;
vector<int>alls;
int find(int x){
	int l=0,r=alls.size()-1;
	while(l<r){
		int mid=(l+r)/2;
		if(alls[mid]>=x) r=mid;
		else l=mid+1;
	}
	return l+1;
}
int lowbit(int x)
{
	return x & -x;
}
int sum(int x)//求x位置前的前缀和
{
	int res=0;
	while(x) res+=tr[x],x-=lowbit(x);
	return res;
}
void add(int x,int c)//在x的位置上加上常数c
{
	while(x<=n) tr[x]+=c,x+=lowbit(x);
}
struct node{
	int l,r;
	bool operator<(const node &W)const{
		return l<W.l;
	}
}q[N];
void solve() {
	cin>>n;
	memset(tr,0,sizeof tr);
	for(int i=1;i<=n;i++) cin>>q[i].l>>q[i].r;
	//离散化
	alls.clear();
	for(int i=1;i<=n;i++){
		alls.push_back(q[i].r);
	}
	sort(alls.begin(),alls.end());
	sort(q+1,q+1+n);
	int ans=0;
	int pos=find(q[1].r);
	add(pos,1);
	for(int i=2;i<=n;i++){
		pos=find(q[i].r);
		int d=sum(pos);
		ans+=i-1-d;
		add(pos,1);                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
	}
	cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
	cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

还有其它的方法,就是我们只要将左端点从小到大排序,然后发现,只要右端点逆序就存在一个包含区间(就是说如果左端点小,但是右端点大,那么它就把一个区间包含住了),所以只要统计逆序对的数量即可,用归并排序

#include
#define endl '\n'
#define int long long
using namespace std;
const int N=2e5+10;
int l[N],r[N];
int c[N];
int n;
int ans;
struct node{
	int l,r;
	bool operator<(const node &W)const{
		return l<W.l;
	}
}q[N];
void mergesort(int l,int r){
	if(l==r) return;
	int mid=(l+r)/2;
	mergesort(l,mid),mergesort(mid+1,r);
	int i=l,j=mid+1,k=0;
	while(i<=mid&&j<=r){
		if(q[i].r<=q[j].r) c[k++]=q[i++].r;
		else{
			c[k++]=q[j++].r;
			ans+=mid-i+1;
		}
	}
	while(i<=mid) c[k++]=q[i++].r;
	while(j<=r) c[k++]=q[j++].r;
	for(int i=l,k=0;i<=r;i++) q[i].r=c[k++];
}
void solve() {
	cin>>n;
	for(int i=1;i<=n;i++) cin>>q[i].l>>q[i].r;
	sort(q+1,q+1+n);
	ans=0;
	mergesort(1,n);
	cout<<ans<<endl;
}
signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int t=1;
    cin>>t;
	while(t--) {
		solve();
	}
	return 0;
}

你可能感兴趣的:(codeforces,算法,c++)