zoukankan      html  css  js  c++  java
  • BZOJ3262陌上花开 树状数组+Treap

    三个属性, 以第一个属性为关键字从小到大排序, 那么考虑一朵花的等级, 只需考虑排在其前面的花的其他属性(特殊情况是有相同的花,根据题意,对一段相同的花,以排在最后的一朵花的答案为准),那么后面的操作就不用考虑第一个属性了 第二三维可以用树状数组加Treap解决, 以每朵花第二属性数值作为位置(因为最大属性k < 2e5, 可以不用离散化, 直接用属性的数值对应树状数组中的下标), 树状数组的每个节点建一颗Treap, 这颗Treap里存的是相应区间里的花的第三个属性, 询问时类似于树状数组求前缀和, 依次将询问的花的位置的前面这一段分成不超过logk棵Treap对应的区间, 在这些区间里可以找出, 由于是以第二属性为位置插入到树状数组里的, 保证前面一段区间的第二属性都是不超过我们询问的花的第二属性, 只要在这不超过logk棵Treap里找出第三属性不超过询问的花的数量, 就是三个属性均不超过询问的花的三个属性的花的数量

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    using namespace std;
    const int maxn = 2e5 + 7, maxk = 2e5 + 7, maxnd = 1e6 + 7;
    
    void readin(int &ret) {
        ret = 0; int f = 1; char ch = getchar();
        while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
        while(ch >= '0' && ch <= '9') ret *= 10, ret += ch - '0', ch = getchar();
        ret *= f;
    }
    
    struct flower {
    	int s, c, m, id, ans;
    	void read() {
    		readin(s); readin(c); readin(m);
    	}
    } f[maxn];
    bool cmp(const flower& a, const flower& b) {
    	return a.s < b.s || (a.s == b.s && a.c < b.c) || (a.s == b.s && a.c == b.c && a.m < b.m);
    }
    
    bool ssame(const flower& a, const flower& b) {
    	return a.s == b.s && a.c == b.c && a.m == b.m;
    } 
    int n, k, siz, ans[maxn], root[maxn], sz[maxnd], val[maxnd], rnd[maxnd], cnt[maxnd], c[maxnd][2];
    void update(int k) {
    	sz[k] = sz[c[k][0]] + sz[c[k][1]] + cnt[k];
    }
    void rotate(int &k, int ch) {
    	int t = c[k][ch]; c[k][ch] = c[t][ch ^ 1]; c[t][ch ^ 1] = k;
    	sz[t] = sz[k]; update(k); k = t;
    }
    void insert(int &k, int x) {
    	if(!k) {
    		val[k = ++siz] = x;
    		rnd[k] = rand();
    		sz[k] = cnt[k] = 1;
    		c[k][0] = c[k][1] = 0;
    	} else if(val[k] == x) sz[k]++, cnt[k]++;
    	else {
    		sz[k]++;
    		int d = val[k] < x;
    		insert(c[k][d], x);
    		if(rnd[c[k][d]] < rnd[k]) rotate(k, d);
    	}
    }
    int find(int k, int x) {
    	if(!k) return 0;
    	if(val[k] == x) return sz[c[k][0]] + cnt[k];
    	if(val[k] > x) return find(c[k][0], x);
    	return sz[c[k][0]] + cnt[k] + find(c[k][1], x);
    } //find(k, x)找出节点k为根的子树中, 权值不大于x的节点数量
    #define lowbit(x) (x&-x)
    void ins(int pos, int x) {
    	while(pos <= k) {
    		insert(root[pos], x);
    		pos += lowbit(pos);
    	}
    }
    int query(int pos, int x) {
    	int ret = 0;
    	while(pos > 0) {
    		ret += find(root[pos], x);
    		pos -= lowbit(pos);
    	}
    	return ret;
    }
    
    int top, stk[maxn], num[maxn];
    int main() {
    	readin(n); readin(k);
    	for(int i = 1; i <= n; i++) f[i].read();
    	sort(f + 1, f + n + 1, cmp);
    	top = 0;
    	for(int i = 1; i <= n; i++) {
    		if(ssame(f[i], f[i + 1])) stk[++top] = i;//如果有相同的花, 先存到数组里, 直到处理了最后一朵这种花再更新前面的答案
    		else {
    			f[i].ans = query(f[i].c, f[i].m);
    			while(top) f[stk[top--]].ans = f[i].ans;
    		}
    		ins(f[i].c, f[i].m);//询问了这朵花后再将这朵花插入树状数组中
    	} 
    	for(int i = 1; i <= n; i++) num[f[i].ans]++;
    	for(int i = 0; i <= n - 1; i++) printf("%d
    ", num[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    数据表格优化
    vue数组和对象的监听变化
    python flask框架搭建以及大佬代码参考
    简单爬虫
    srs的基本配置
    记录飞天程序库调用
    面试题 递归算法1+2+....+100求和
    下载列表组件
    Prometheus之系统安装,启动
    nginx之日志
  • 原文地址:https://www.cnblogs.com/usingnamespace/p/5205344.html
Copyright © 2011-2022 走看看