首页 > 其他分享 >CF961E Tufurama 题解

CF961E Tufurama 题解

时间:2023-09-30 09:15:31浏览次数:50  
标签:geq yrk Tufurama int 题解 CF961E leq xx 统计

CF961E Tufurama 题解

二维数点做法

题意

  给定长度为 \(n\) 的序列 \(a\),统计二元组 \((i,j)\) 的个数,使得该二元组满足 \(1 \leq i < j \leq n, a_i \geq j, a_j \geq i\)。\(n\) 在 \(2 \times 10^{5}\) 级别,\(a_i\) 在 \(1 \times 10^{9}\) 级别。

思路分析

  我们考虑把序列中 \(n\) 个元素看成 \((i,a_i)\) 坐标的点,至于平面直角坐标系中。我们先忽略“\(1 \leq i < j \leq n\)”的条件。可以发现,对于某一个 \(i\),我们要统计的是所有的 \(j\) 中满足 \(j \leq a_i, a_j \geq i\) 的点的个数,也就是横坐标小于等于当前点、纵坐标大于等于当前点的点的个数。画出图就是下面的样子:

图片1

  至于具体怎么处理数点过程,我们按照先横坐标再纵坐标的方式对于点排序。然后我们可以把每个询问 \((a_i,i)\) 做排序,代表查询横坐标小于等于 \(a_i\),纵坐标大于等于 \(i\) 的点的个数。我们横坐标从小到大一列一列地统计点(即一根扫描线在 x 轴上从小往大扫),用树状数组维护纵坐标上离散化过后的每个位置的已统计点的点数前缀和,统计纵坐标大于等于 \(i\) 的区间内的点数,就可以知道对应的答案了。

  那么我们怎么处理 \(1 \leq i < j \leq n\) 的条件呢?首先我们考虑在的统计中,出现的 \(i = j\) 的情况,可以发现,如果这样的情况被统计到了,(代入条件可得)就会满足 \(a_i \geq i, a_i \geq i\),于是我们直接在序列上遍历统计 \(a_i \geq i\) 的个数,在总统计答案中减掉就行。

  然后就是 \(i < j\) 的条件如何处理,我们发现 \(a_i \geq j, a_j \geq i\) 和 \(a_j \geq i, a_i \geq j\)(即交换 \(i,j\) 后)是等效的,也就是说每一个满足条件的点对被统计了两遍。于是我们在刚刚的基础上,把统计答案除以二,就得到了正确结果。

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;

const int N = 5e5 + 5;
const int M = 5e5 + 5;

int n,m;
int a[N];
int ycnt;

int qcnt;
int yrk[N];

struct quest
{
	int x,y;
}que[N*2];

int ans[N];

bool cmp1(quest xx,quest yy)
{
	return xx.x < yy.x;
}

int t[N];

int lowbit(int xx)
{
	return xx & (-xx);
}

void add(int pos,int k)
{
	for(int i = pos;i <= ycnt;i += lowbit(i))
		t[i] += k;
}

int ask(int pos)
{
	int ans = 0;
	for(int i = pos;i >= 1;i -= lowbit(i))
		ans += t[i];
	return ans;
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin >> n;
	LL samecnt = 0;
	for(int i = 1;i <= n;i++)
	{
		cin >> a[i];
		if(a[i] >= i)
			samecnt++;
		yrk[i] = a[i];
		que[++qcnt] = {a[i],i};
	}
	sort(que+1,que+1+n,cmp1);
	sort(yrk+1,yrk+1+n);
	ycnt = unique(yrk+1,yrk+1+n)-1-yrk;
	int idx = 1;
	LL ans = 0;
	for(int i = 1;i <= n;i++)
	{
		while(idx <= que[i].x && idx <= n)
		{
			int tmpidx = lower_bound(yrk+1,yrk+1+ycnt,a[idx])-yrk;
			add(tmpidx,+1);
			idx++;
		}
		int tmpfd = lower_bound(yrk+1,yrk+1+ycnt,que[i].y)-yrk-1;
		ans += (LL)(ask(ycnt)-ask(tmpfd));
	}
	ans -= samecnt;
	ans /= 2;
	cout << ans << "\n";
	return 0;
}

标签:geq,yrk,Tufurama,int,题解,CF961E,leq,xx,统计
From: https://www.cnblogs.com/l-cacherr/p/17737587.html

相关文章

  • [题解] CF1003E - Tree Constructing
    CF1003E-TreeConstructing题目传送门知识点:贪心题意给定\(n\)个顶点,问是否能够构造出一棵直径为\(d\)的树,且每个顶点的度数最多为\(k\)。思路我们要构造出一棵树,使得其直径长度一定为\(d\),那么我们可以先选择\(d+1\)个点,让这些点构成一条树链即可。接着,考虑......
  • P5047 [Ynoi2019 模拟赛] Yuno loves sqrt technology II 题解
    Description给你一个长为\(n\)的排列,\(m\)次询问,每次查询一个区间的逆序对数,强制在线。link\(1\leqn,m\leq10^5\)。Solution考虑分块。首先如果\(l,r\)在同一个块内,可以对于每个块暴力二维前缀和预处理。如果\(l,r\)在不同的块内。设\(bel[l]=x,bel[r]=y\)。首......
  • CSP-S 2021 廊桥分配 题解
    part1:题目描述:当一架飞机抵达机场时,可以停靠在航站楼旁的廊桥,也可以停靠在位于机场边缘的远机位。乘客一般更期待停靠在廊桥,因为这样省去了坐摆渡车前往航站楼的周折。然而,因为廊桥的数量有限,所以这样的愿望不总是能实现。机场分为国内区和国际区,国内航班飞机只能停靠在国内......
  • [CF762D] Maximum path 题解
    [CF762D]Maximumpath题解想法首先考虑问题的弱化版,如果不能往左走,能取到的最大值是多少。这个问题可以用一个显然的DP解决,\(f_{i,j}\)表示走到第\(i\)列,第\(j\)行,并且不会再访问这一列其它的方格,能取到的最大值。转移可以从三个方向考虑,以\(f_{i,1}\)为例,黑色是当......
  • P2216 [HAOI2007] 理想的正方形 题解
    Description给定\(n\timesm\)的矩阵,找大小为\(k\timesk\)的子矩阵\(a\),使得子矩阵\(\max\{a\}-\min\{a\}\)最小。SolutionSolution1枚举所有\(k\timesk\)的子矩阵,然后枚举最大值和最小值,时间复杂度\(O(n^4)\),期望得分\(20\)分。Solution2求最大值和最小......
  • CF1425F Flamingoes of Mystery 题解
    题目传送门前置知识前缀和&差分解法令\(sum_k=\sum\limits_{i=1}^{k}a_k\)。考虑分别输入\(sum_2\simsum_n\),故可以由于差分知识得到\(a_i=sum_i-sum_{i-1}(3\lei\len)\),接着输入\(a_2+a_3\)的值从而求出\(a_2=sum_3-a_3,a_1=sum_2-a_2\)。同时因为是交互题,记......
  • 【题解】[CQOI2008] 传感器网络
    题意给定一张有向无环图,从中选出一棵有根树(节点编号为\(0\simn\),树根为\(n\)),使得除根节点外所有节点的出度的最大值最小。除根节点外,依次输出每个节点的父亲,并要求字典序最小。(\(1\len\le50\))*注意:由于个人习惯,这里将节点编号重编为\(1\simn+1\),根节点即为\(n+1\)......
  • 雅思 outweigh 议论题解答方法
    Doyouthinktheadvantagesoutweighthedisadvantages?1.这是两面写作题2.必须分出多少/高低3.所以说这个题目基本等同于discuss的弱强写作结构,不要给自己增加负担觉得新学了一种题目。结构安排:1.引出争论/背景句+给出明确的偏向(…..doesmoregoodthan harm.)2.先......
  • Broken robot 题解
    题目链接Rrokenrobot分析记\(f[i][j]\)为从\(i\)行\(j\)列到最后一行的期望,则\(f[i][j]=\begin{cases}\frac{1}{3}(f[i][j]+f[i][j+1]+f[i+1][j])+1&i=1\\\frac{1}{4}(f[i][j]+f[i][j-1]+f[i,j+1]+f[i+1][j])+1&1<i<m\\\frac{1}{3}(f[i][j]......
  • git clone项目报错fatal: fetch-pack: invalid index-pack output问题解决
    gitclone项目报错fatal:fetch-pack:invalidindex-packoutput问题解决原因出现该问题的原因是gitclone的项目过大导致项目拉去失败解决方法首先拉去项目最后一次提交gitclone--depth=1项目地址;拉取全部项目内容gitfetch--unshallow,一般不大的项目都可以......