zoukankan      html  css  js  c++  java
  • Codeforces 669E cdq分治

    题意:你需要维护一个multiset,支持以下操作:

    1:在某个时间点向multiset插入一个数。

    2:在某个时间点在multiset中删除一个数。

    3:在某个时间点查询multiset的某个数的个数。

    思路:该题相当于要构建一个在任意位置插入,并查询前缀操作的某个值的多少。乍一看比较棘手,搞不好还要数据结构的嵌套。但是转化一下思路,用cdq分治这题非常简单。分治过程中按时间排序即可,用map维护前半部分产生的影响,后面如果有查询在map中查询即可。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn = 100010;
    struct query{
    	int flag, t, val, id;
    };
    query q[maxn], tmp[maxn];
    int ans[maxn], tot;
    map<int, int> mp;
    void cdq(int l, int r) {
    	if(l == r) return;
    	int mid = (l + r) >> 1;
    	cdq(l, mid);
    	cdq(mid + 1, r);
    	int l1 = l, l2 = mid + 1, pos = l;
    	mp.clear();
    	while(l1 <= mid && l2 <= r) {
    		if(q[l1].t < q[l2].t) {
    			if(q[l1].flag == 1) mp[q[l1].val]++;
    			else if(q[l1].flag == 2) mp[q[l1].val]--;
    			tmp[pos++] = q[l1++];
    		} else {
    			if(q[l2].flag == 3) {
    				ans[q[l2].id] += mp[q[l2].val];
    			}
    			tmp[pos++] = q[l2++];
    		}
    	}
    	while(l1 <= mid) tmp[pos++] = q[l1++];
    	while(l2 <= r) {
    		if(q[l2].flag == 3) {
    			ans[q[l2].id] += mp[q[l2].val];
    		}
    		tmp[pos++] = q[l2++];
    	}
    	for (int i = l; i <= r; i++)
    		q[i] = tmp[i];
    }
    int main() {
    	int n;
    	scanf("%d", &n);
    	for (int i = 1; i <= n; i++) {
    		scanf("%d%d%d", &q[i].flag, &q[i].t, &q[i].val);
    		if(q[i].flag == 3) q[i].id = ++tot;
    	}
    	cdq(1, n);
    	for (int i = 1; i <= tot; i++) {
    		printf("%d
    ", ans[i]);
    	}
    } 
    

      

  • 相关阅读:
    js实现字符串反转
    网页中嵌入百度地图
    Javascript创建对象方法
    使用@font-face来实现icon
    关于课程实验的反思
    Factory设计模式构建
    正则表达式的应用
    IO流
    解读main()方法中的String[] args
    技术与运营
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/11158838.html
Copyright © 2011-2022 走看看