首页 > 其他分享 >AtCoder Beginner Contest 346 G

AtCoder Beginner Contest 346 G

时间:2024-04-01 21:47:03浏览次数:25  
标签:AtCoder last Beginner int ll 346 MAXN line

# G - Alone (atcoder.jp)

ABC 346 这一场来说相对比较简单,F是一个细节比较多的二分,G也算是一个比较板子的题。

简单说一下 G 题的思路。

其实比较容易想到用两个数组维护第 i 个数 \(a_i\) 在第 i 位之前出现的位置,以及第 i 个数在第 i 位之后出现的位置。那么当前位的能够满足的区间就为 \((i - last_i) * (next_i - i)\)

image-20240401212122423

但是每一位都这样算会有重复,我们考虑一下如何去重。

对于第一组样例:

5
2 2 1 2 1

image-20240401212226782

我们发现相乘的本质实际上与分布原理有一定关系,于是把对应的区间画出来。

image-20240401212341024

可以得到上图,我们再联系一下,从两个不同区间选两个数的方案数等于两个不同区间元素个数乘积,画图即矩形的面积。

image-20240401212551054

会发现所有矩形的并的面积即是答案,不难想到扫描线算法。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MAXN = 5e5+5;
ll X[MAXN], n, ans, a[MAXN];
ll l[MAXN];
ll last[MAXN], nxt[MAXN];
struct line{
	ll x1, x2, y;
	ll tag;
}L[MAXN];
bool operator < (line xx, line yy){
	return xx.y < yy.y;
}
struct node{
	ll l, r;
	int cnt, len;
}tr[MAXN << 3];
void build(ll x, ll l, ll r){
	tr[x] = {l, r, 0, 0};
	if(l == r) return;
	ll mid = l + r >> 1;
	build(x << 1, l, mid);
	build(x << 1 | 1, mid + 1, r);
}
void pushup(ll x){
	ll l = tr[x].l, r = tr[x].r;
	if(tr[x].cnt) tr[x].len = X[r + 1] - X[l];
	else tr[x].len = tr[x << 1].len + tr[x << 1 | 1].len;
}
void modify(ll x, ll l, ll r, ll w){
	if(tr[x].r < l || r < tr[x].l) return;
	if(l <= tr[x].l && tr[x].r <= r){
		tr[x].cnt += w;
		pushup(x);
		return;
	}
	modify(x << 1, l, r, w);
	modify(x << 1 | 1, l, r, w);
	pushup(x);
}
int main(){
	ios::sync_with_stdio(false);
	cin >> n;
	for(int i = 1; i <= n; i ++){
		cin >> a[i];
		last[i] = l[a[i]];
		nxt[l[a[i]]] = i;
		nxt[i] = n + 1;
		l[a[i]] = i;
	}
	for(int i = 1; i <= n; i ++){
		L[i] = {last[i], i, i, 1};
		L[n + i] = {last[i], i, nxt[i], -1};
		X[i] = last[i];
		X[n + i] = i;
	}
	n <<= 1;
	sort(L + 1, L + n + 1);
	sort(X + 1, X + n + 1);
	int len = unique(X + 1, X + n + 1) - (X + 1);//去重 因为从 1开始所以减 x+1
	build(1, 1, len - 1);
	unordered_map<ll, ll> mp;
	for(int i = 1; i <= len; i ++){
		mp[X[i]] = i;
	}
	for(int i = 1; i < n; i ++){
		modify(1, mp[L[i].x1], mp[L[i].x2] - 1, L[i].tag);
		ans += tr[1].len * (L[i + 1].y - L[i].y);
//		cout << L[i].y << endl;
	}
	cout << ans << endl;
	return 0;
}

标签:AtCoder,last,Beginner,int,ll,346,MAXN,line
From: https://www.cnblogs.com/XiaoMo247/p/18109434

相关文章

  • [ABC347] AtCoder Beginner Contest 347 题解
    [ABC347]AtCoderBeginnerContest347题解A模拟。BSA模板,把所有子串丢进哈希表里即可。C逆天题,这个分讨并不显然。考虑计算所有天数到今天的偏移量,然后如果最远的和最近的天数的距离\(\leA\)肯定可以,否则可以把所有天向右平移一段距离,然后使得最远的天到达第二周的......
  • AtCoder Beginner Contest 347 A-F 题解
    A-DivisibleQuesiton给你正整数\(N\)和\(K\),以及长度为\(N\)的序列\(A\)。提取\(A\)中所有是\(K\)倍数的元素,除以\(K\),并打印商。Solution判断\(A_i\%K\)的值是否为\(0\),如果非\(0\)则表示可以整除Code#include<bits/stdc++.h>usingnamespacest......
  • AtCoder Beginner Contest 347 (A~E)
    #AtCoderBeginnerContest347(A~E)这场C>E>D不好评价...(DE赛后一发过,被C卡死了)A模拟即可。#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;constllN=2e5+5;lln,k,a[N];intmain(){ ios::sync_with_stdio(false); cin>>......
  • AtCoder Beginner Contest 347
    ATlinkProblemAandB略。ProblemC按照模\(a+b\)分类,记录最大值和最小值,如果差值小于等于假期时间即可,否则还需要判断按照\(d_i=D_i\bmod(a+b)\)排序后相邻的两个是否满足条件。ProblemD分离出\(C\)的二进制位,然后对于每一位\(c_i>0\)尝试在\(A,B\)......
  • AtCoder Beginner Contest 347
    A-Divisible(abc347A)题目大意给定\(n\)个数\(a_i\)以及\(k\),输出是\(k\)的倍数的\(a_i\)整除以\(k\)的值。解题思路按照题意判断取模和求整除即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){ios::syn......
  • AtCoder Beginner Contest 347
    很快做完了AB。然后C就不会做了。随便想了个看似正确的就交了,结果WA*1。后来有交了4发,一发比一发离谱。发现D不难,是一个状态数\(60\times60\times60\)的DP,但是貌似细节很多。写了大约20分钟后无伤过了,发现压根没有需要处理的细节。这时是57min。读完E......
  • atcoder beginner 346 题解
      看到别人的视频讲解 AtCoderBeginnerContest346A至G題讲解bydreamoon C如果用sort写,那么再从小到大遍历也需要写几行#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<cstdbool>#include<string>#include<......
  • AtCoder Beginner Contest 346
    AtCoderBeginnerContest346比赛链接A-AdjacentProduct思路:b[i]=a[i]*a[i+1]Code#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong#defineall(x)x.begin()+1,x.end()voidsolve(){ intn; cin>>n; std::vector<in......
  • Atcoder
    D-食塩水\[\frac{\sum{w_ip_i}}{\sum{w_i}}\gex\\\sum{w_i(p_i-x)}\ge0\\\]fromcollectionsimport*fromitertoolsimport*fromfunctoolsimport*defLI():returnlist(map(int,input().split()))defI():returnint(input())de......
  • abc346
    D-GomamayoSequence给定\(N\)长的01字符串,使其满足,只有一个下标\(i,S_{i}=S_{i+1}\)对于\(S_i\),他改变的花费为\(C_i\),若\(S_i=0,则它变为1,否则变为0\)因为只有一对相同的字符组(i,i+1)维护\(1-i\)以\(j\in{0,1}\)结尾的01交替串的花费维护\(i-结尾\)以......