• 【题解】 CF1418G Three Occurrences hash+双指针+差分


    Legend

    Link ( extrm{to Codeforces})

    给定长度为 (n (1 le n le 5 imes 10^5)) 的序列,一个序列称作是好的当且仅当序列中所有元素出现恰好 (3) 次。

    请求出这个序列有多少个连续子序列是好的

    Editorial

    做数据结构时候做到的。。。以为是什么神仙数据结构。。。结果看了下 ( m{tag:hash})

    注意题目中的条件,数字出现恰好 (3) 次。可以把同样的数字按顺序给定 (3) 个哈希值 (v_1,v_2,v_3),(每个数字的哈希值不同)

    并且满足 (v_1 operatorname{xor} v_2 operatorname{xor} v_3 = 0)

    这样子做只要一个区间异或和为 (0) 就说明有很大概率说明所有数字出现的次数都是 (3) 的倍数。

    我们只要通过双指针卡着区间就可以确保每个数字出现次数都是 (3) 次以内。hash 加差分应该是个套路不赘述。

    复杂度 (O(n log n))

    Code

    ( m{Codeforces}),单哈希会把你卡到生不如死。

    所以还是老老实实写双哈希吧!

    #include <bits/stdc++.h>
    
    #define ULL unsigned long long
    #define mp make_pair
    #define p pair<ULL ,ULL>
    
    using namespace std;
    
    map<p ,int> MAP;
    
    int read(){
    	char k = getchar(); int x = 0;
    	while(k < '0' || k > '9') k = getchar();
    	while(k >= '0' && k <= '9') x = x * 10 + k - '0' ,k = getchar();
    	return x;
    }
    
    const int MX = 5e5 + 233;
    int app[MX] ,a[MX];
    ULL rnd[3][MX] ,cnt[MX] ,ha[MX] ,ha2[MX];
    ULL rnd2[3][MX];
    
    ULL r(){
    	return ((ULL)(rand()) << 31) ^ rand();
    }
    
    int main(){
    	srand(19260817);
    	int n = read();
    	for(int i = 1 ; i < MX ; ++i){
    		rnd[0][i] = r();
    	   	rnd[1][i] = r();
    		rnd[2][i] = rnd[0][i] ^ rnd[1][i];
    		rnd2[0][i] = r();
    	   	rnd2[1][i] = r();
    		rnd2[2][i] = rnd2[0][i] ^ rnd2[1][i];	
    	}
    
    	int l = 1;
    	ULL Ans = 0;
    	MAP[mp(0ull ,0ull)] = 1; app[0] = 1;
    	for(int i = 1 ; i <= n ; ++i){
    		a[i] = read();
    		ha[i] = ha[i - 1] ^ rnd[cnt[a[i]]][a[i]];
    		ha2[i] = ha2[i - 1] ^ rnd2[cnt[a[i]]][a[i]];
    		cnt[a[i]] = (cnt[a[i]] + 1) % 3;
    		while(app[a[i]] == 3){
    			--app[a[l]];
    			--MAP[mp(ha[l - 1] ,ha2[l - 1])];
    			++l;
    		}
    		++app[a[i]];
    		Ans += MAP[mp(ha[i] ,ha2[i])];
    		// fprintf(stderr ,"i = %d ,Ans = %llu
    " ,i ,Ans);
    		++MAP[mp(ha[i] ,ha2[i])];
    	}
    	cout << Ans << endl;
    	return 0;
    }
    
  • 相关阅读:
    怎么知道银行卡号对应的银行
    集合排序、map、枚举
    669. Trim a Binary Search Tree修剪二叉搜索树
    17. Merge Two Binary Trees 融合二叉树
    226. Invert Binary Tree 翻转二叉树
    530.Minimum Absolute Difference in BST 二叉搜索树中的最小差的绝对值
    191. Number of 1 Bits 二进制中1的个数
    Hamming Distance二进制距离
    136. Single Number唯一的数字
    276. Paint Fence篱笆涂色
  • 原文地址:https://www.cnblogs.com/imakf/p/13700231.html
Copyright © 2020-2023  润新知