三元組[01 Trie計數]

也許更好的閱讀體驗

Description\mathcal{Description}

在這裏插入圖片描述

Solution\mathcal{Solution}

有兩種方法都可以拿到滿分

Solution 1Solution\ 1

考慮枚舉yy
建兩個01Trie01Trie,要支持刪除操作
一顆TrieTrie維護yy左邊的信息
一顆TrieTrie維護yy右邊的信息
在枚舉yy的時候左邊的添加,右邊的刪除,可做到loglog維護,建樹是nlognlog
暴力的想法是兩個TrieTrie一起跑,枚舉在哪一位開始不一樣,前面的情況也都枚舉,這樣的情況最壞是22的指數級別,可以拿到5050
考慮優化這個過程
因爲每次只會刪去一條鏈,所以考慮這條鏈被刪去所帶來的影響
f[i][0/1]f[i][0/1]表示到第ii位開始不一樣的答案
每次刪除時只少了一條鏈,所以把這條鏈的情況減去
增加時加上新的情況即可

Solution 2Solution\ 2

這種方法相對來說代碼量要少很多
考慮枚舉zz
用一顆TireTire表示前面的信息
仍然考慮枚舉在哪一位開始不一樣(d)(d)
s[i][0/1]s[i][0/1]表示前面所有在第ii位爲0/10/1的串的總數
sum[i]sum[i]表示TireTireii號節點有多少個不合法的(x,y)(x,y)(y<x)(y<x)
cnt[i]cnt[i]表示TireTire上經過ii的個數
由於枚舉的是zz,我們對yy的要求只有 枚舉到dd時,其在dd00還是11
假設枚舉到的zz的值在dd位是cc
答案就是cnt[原本串中和zzdd前面的位相同]×s[d][!c]\times s[d][!c]-不合法的(x,y)(x,y)對數
具體可看代碼

Code\mathcal{Code}

Solution 2Solution\ 2
因爲這種好實現些,所以就寫的這種

/*******************************
Author:Morning_Glory
LANG:C++
Created Time:2019年09月23日 星期一 19時48分07秒
*******************************/
#include <cstdio>
#include <fstream>
#include <cstring>
#define ll long long
#define reset(x) memset(x,0,sizeof(x))
using namespace std;
const int maxn = 3000006;
const int lim = 29;
//{{{cin
struct IO{
	template<typename T>
	IO & operator>>(T&res){
		res=0;
		bool flag=false;
		char ch;
		while((ch=getchar())>'9'||ch<'0')	flag|=ch=='-';
		while(ch>='0'&&ch<='9')	res=(res<<1)+(res<<3)+(ch^'0'),ch=getchar();
		if (flag)	res=~res+1;
		return *this;
	}
}cin;
//}}}
int T,n,v,tot;
int ch[maxn][2],s[lim+1][2];
ll sum[maxn],cnt[maxn];
void insert (int rt,int v,int d)
{
	if (d<0)	return;
	int c=(v>>d)&1;
	if (!ch[rt][c])	ch[rt][c]=++tot;
	rt=ch[rt][c];
	++cnt[rt],sum[rt]+=++s[d][c];
	insert(rt,v,d-1);
}
ll query (int rt,int v,int d)
{
	if (d<0)	return 0;
	int c=(v>>d)&1,p=ch[rt][c^1];
	return cnt[p]*s[d][c^1]-sum[p]+query(ch[rt][c],v,d-1);
}
int main()
{
	cin>>T;
	while (T--){
		cin>>n;
		ll ans=tot=0;
		reset(sum),reset(s),reset(ch),reset(cnt);
		for (int i=1;i<=n;++i){
			cin>>v;
			insert(0,v,lim);
			ans+=query(0,v,lim);
		}
		printf("%lld\n",ans);
	}
	return 0;
}

如有哪裏講得不是很明白或是有錯誤,歡迎指正
如您喜歡的話不妨點個贊收藏一下吧

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章