zoukankan      html  css  js  c++  java
  • BZOJ5016 SNOI2017 一个简单的询问 莫队、前缀和、容斥

    传送门——BZOJ


    THUWC2019D1T1撞题可还行

    以前有些人做过还问过我,但是我没有珍惜,直到进入考场才追悔莫及……

    (que_{i,j})表示询问((1,i,1,j))的答案,那么询问((a,b,c,d)=que_{b,d} - que_{a-1 , d} - que_{b , c - 1} + que_{a - 1 , c - 1})

    把一个询问拆成(4)个询问,然后对这(4)个询问莫队就可以了

    不知道怎么回事THUWC上想到了莫队想到了前缀和想到了容斥就是没想到莫队+前缀和+容斥……

    #include<bits/stdc++.h>
    //This code is written by Itst
    using namespace std;
    
    inline int read(){
    	int a = 0;
    	char c = getchar();
    	bool f = 0;
    	while(!isdigit(c) && c != EOF){
    		if(c == '-')
    			f = 1;
    		c = getchar();
    	}
    	if(c == EOF)
    		exit(0);
    	while(isdigit(c)){
    		a = a * 10 + c - 48;
    		c = getchar();
    	}
    	return f ? -a : a;
    }
    
    const int MAXN = 5e4 + 3;
    int N , M , T , cnt , cntQ;
    int arr[MAXN] , times[MAXN][2];
    long long ans[MAXN] , cur;
    struct query{
    	int p1 , p2 , ind , flg;
    	query(int a = 0 , int b = 0 , int c = 0 , int d = 0):p1(a) , p2(b) , ind(c) , flg(d){}
    	bool operator <(const query b)const{
    		return p1 / T == b.p1 / T ? p2 < b.p2 : p1 < b.p1;
    	}
    }que[MAXN << 2];
    
    inline void add(int a , int ind){
    	cur += times[a][ind ^ 1];
    	++times[a][ind];
    }
    
    inline void del(int a , int ind){
    	cur -= times[a][ind ^ 1];
    	--times[a][ind];
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
    	freopen("in","r",stdin);
    	freopen("out","w",stdout);
    #endif
    	N = read();
    	T = sqrt(N);
    	for(int i = 1 ; i <= N ; ++i)
    		arr[i] = read();
    	M = read();
    	for(int i = 1 ; i <= M ; ++i){
    		int a = read() , b = read() , c = read() , d = read();
    		que[++cntQ] = query(b , d , i , 1);
    		if(a - 1)
    			que[++cntQ] = query(a - 1 , d , i , -1);
    		if(b - 1)
    			que[++cntQ] = query(b , c - 1 , i , -1);
    		if(a - 1 && b - 1)
    			que[++cntQ] = query(a - 1 , c - 1 , i , 1);
    	}
    	sort(que + 1 , que + cntQ + 1);
    	int l1 = 0 , l2 = 0;
    	for(int i = 1 ; i <= cntQ ; ++i){
    		while(l1 < que[i].p1)
    			add(arr[++l1] , 0);
    		while(l1 > que[i].p1)
    			del(arr[l1--] , 0);
    		while(l2 < que[i].p2)
    			add(arr[++l2] , 1);
    		while(l2 > que[i].p2)
    			del(arr[l2--] , 1);
    		ans[que[i].ind] += que[i].flg * cur;
    	}
    	for(int i = 1 ; i <= M ; ++i)
    		cout << ans[i] << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    1.14验证码 彩票
    String代码示例
    1.13作业
    控制台输入人数和分数 自动判断最高分最低分
    对矩阵进行转置运算
    16、输入三角形的三个边,求其面积
    02、
    15、判断字符串是否回文——字符串
    14、求出最大元素的下标及地址值——数组
    13、字符串在指定的地方以及元素个数实行逆置——字符串
  • 原文地址:https://www.cnblogs.com/Itst/p/10320391.html
Copyright © 2011-2022 走看看