删除(未挖宝)

文章目录

  • ——2021年02月21日(周日)——————————————————
  • 树状数组
    • 一、Stars POJ - 2352 (星星)
    • 二、逆序对
    • 三、P3374 【模板】树状数组 1
    • 四、P3368 【模板】树状数组 2
    • 五、P3372 【模板】线段树 1
    • 六、P2068 统计和
  • ——2021年02月22日(周一)——————————————————
  • ——2021年02月23日(周二)——————————————————
    • 七、火柴排队

——2021年02月21日(周日)——————————————————

树状数组

一、Stars POJ - 2352 (星星)

题目点这里

树状数组的正确性证明:
由于y和x是已经从小到大排好序的,
所以往后枚举的顺序是先从低到高,再从左到右。
1.所以当前的query数组里的元素,是不会包含y以上的stars的,
2.而且x是按照顺序相加的,所以query[x]是不会包含x后面的stars的,因为query[x]最终可以求得前面的x相加的和。
于是就满足了 在左边和下边的stars的总数 这个条件
总结: 所以,这道题之所以会用到树状数组,是因为这个求和的顺序巧妙地契合树状数组的求和特点

#include 
#include 
using namespace std;
//c是树状数组 
int n, c[32005], ans[15005]; 

struct N {
   
	int x, y;
}p[15005];


void update(int x, int v) {
   
	for (int i = x; i <= 32005; i += i & (-i)) {
   
		c[i] += v;
	}
} 
//求和
int query(int x) {
   
	int ans = 0;
	for (int i = x; i > 0; i -= i & (-i)) {
   
		ans += c[i];
	}
	return ans;	
}
int main() {
   
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
   
		scanf("%d%d", &p[i].x, &p[i].y);
		//由于x坐标可能为0 所以进行++,树状数组不能维护0这个点 
		p[i].x ++;
	}
	for (int i = 1; i <= n; i++) {
   
		ans[query(p[i].x)]++;
		update(p[i].x, 1);
	}
	for (int i = 0; i < n; i++) {
   
		printf("%d\n", ans[i]);
	}
	return 0;
} 

二、逆序对

题目

跑去复习了一下:这里这里
发现有些东西忘了,忘得很干净……

#include
#include
#include
using namespace std;
int tree[500010], r[500010], n;
long long ans; 
struct point
{
   
    int num,val;
}a[500010];

bool cmp(point q, point w)
{
   
    if(q.val == w.val)
        return q.num < w.num;
    return q.val < w.val;
}

void insert(int p, int d)
{
   
    for(; p <= n; p += p & -p)
        tree[p] += d; 
}
int query(int p)
{
   
    int sum = 0;
    for(; p; p -= p & -p)
        sum += tree

你可能感兴趣的:(刷题记录)