zoukankan      html  css  js  c++  java
  • hihocoder1236(2015长春网赛J题) Scores(bitset && 分块)

    题意:给你50000个五维点(a1,a2,a3,a4,a5),50000个询问(q1,q2,q3,q4,q5),问已知点里有多少个点(x1,x2,x3,x4,x5)满足(xi<=qi,i=1,2,3,4,5),强制在线。

    一看题的一个直接思路是五维树状数组,算了一下复杂度还不如暴力判,遂不会做。赛后问了一下大神们,知道是分块+bitset,觉得处理挺巧妙的,就留一份题解在这里。

    具体的做法是这样子的。定义一个bitset<maxn> bs[i][k],表示第i维前k块所对应的点的bitset,之所以要分块是因为不分块的话空间开不下。所以现在每一个询问过来,其实就是对每一维求出所有比它小的bitset,这些bitset & 起来的结果的count就是要求的答案。

    我觉得这里比较玄妙的点是分块bitset,用分块去避开空间不够的影响在很多优化的问题上都是挺有帮助的。

    #pragma warning(disable:4996)
    #include<algorithm>
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    #include<iostream>
    #include<queue>
    #include <list>
    #include<time.h>
    #include<bitset>
    using namespace std;
    
    #define maxn 50005
    
    struct Node
    {
    	int val, id;
    	Node(int _val, int _id) :val(_val), id(_id){}
    	Node(){}
    	bool operator < (const Node &b)const{
    		if (val == b.val) return id < b.id;
    		return val < b.val;
    	}
    }a[6][maxn];
    int n,m,q;
    
    bitset<maxn> bs[5][250];
    int block_num;
    int per_block;
    
    int main()
    {
    	int T; cin >> T;
    	while (T--)
    	{
    		cin >> n >> m;
    		for (int i = 0; i < n; ++i){
    			for (int j = 0; j < 5; ++j){
    				scanf("%d", &a[j][i].val);
    				a[j][i].id = i;
    			}
    		}
    		for (int i = 0; i < 5; ++i) sort(a[i], a[i] + n);
    		block_num = sqrt(n + .0);
    		per_block = ceil(n / (block_num + .0));
    
    		for (int i = 0; i < 5; ++i){
    			for (int k = 0; k < block_num; ++k){
    				bs[i][k].reset();
    			}
    		}
    
    		for (int i = 0; i < 5; ++i){
    			for (int j = 0; j < n; ++j){
    				bs[i][j / per_block].set(a[i][j].id);
    			}
    		}
    
    		for (int i = 0; i < 5; ++i){
    			for (int j = 0; j < block_num; ++j){
    				if (j) bs[i][j] |= bs[i][j - 1];
    			}
    		}
    
    		cin >> q;
    		int ans = 0;
    		bitset<maxn> res, tmp;
    		int d;
    		while (q--)
    		{
    			res.set();
    			for (int k = 0; k < 5; ++k){
    				tmp.reset();
    				scanf("%d", &d);
    				d ^= ans;
    				int index = upper_bound(a[k], a[k] + n, Node(d, n + 1)) - a[k] - 1;
    				if (index < 0){
    					res.reset();
    					continue;
    				}
    				if (index / per_block) {
    					tmp = bs[k][index / per_block - 1];
    				}
    				int start = (index / per_block)*per_block;
    				int end = index;
    				for (int i = start; i <= end; ++i){
    					tmp.set(a[k][i].id);
    				}
    				res &= tmp;
    			}
    			ans = res.count();
    			printf("%d
    ", ans);
    		}
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    OOm是否可以try catch ?
    Java中两个线程是否可以同时访问同一个对象的两个不同的synchronized方法?
    PHP请求ws出现的问题
    AndFix注意事项
    thinkphp 查表返回的数组,js解析有UNICode编码,解决办法
    thinkphp用ajax遇到的坑——ajax请求没有反应
    用php获取js变量的值
    android项目安装报错:INSTALL_FAILED_CONFLICTING_PROVIDER
    96
    wuti
  • 原文地址:https://www.cnblogs.com/chanme/p/4829903.html
Copyright © 2011-2022 走看看