首页 > 其他分享 >CF241B Friends

CF241B Friends

时间:2023-12-22 19:33:38浏览次数:26  
标签:int ll mid tot trie CF241B Friends c1

异或粽子的加强版,时间复杂度是 \(O(n log^2 w)\) ,其中 \(w\) 是值域 \(2^{30}\) ,原来的是和 \(k\) 有关的,相当于是 CF241B 的代码通过不了异或粽子,异或粽子的代码通过不了 CF241B(雾

先考虑一个整体的思路,求前 \(k\) 大,先需要求第 \(k\) 大,第 \(k\) 大直接先二分,然后判断 \(mid\) 的排名,所以子问题是在字典树上判断两两异或值大于等于 \(mid\) 的个数

要求大于等于 \(mid\) ,也就是说二进制下存在一个位置它是 1 且 \(mid\) 是 0 ,它之前的都和 \(mid\) 一样,那直接枚举每个数,然后在字典树上跳,如果 \(mid\) 这位是 1 的话就直接跳,如果是 0 的话,就统计是 1 的答案,然后跳 0 ,统计一下,因为贡献会互相算一次,所以算了两次,要除一下

那么现在求完了第 \(k\) 大,我们要求前 \(k\) 大的 \(a_i\oplus a_j\) 和,直接枚举 \(a_i\) ,现在就是要求大于 \(kth\) ,如果这位 \(kth\) 是 1 就直接跳,如果是 0 就先统计再跳,跟之前差不多,但是统计的时候要统计这样一个东西:以 \(i\) 为根节点的子树内第 \(k\) 位为 1 的数的个数。再统计直接枚举位数就好了,如果这 \(a_i\) 这一位是1的话,要容斥一下,统计的话就是算贡献,乘 \(2^k\) ,很常见的算贡献方式。记得最后要除 2

但是要注意,如果有数和第 \(k\) 大相同就要减掉那些数

#include<bits/stdc++.h>
#define il inline 
#define maxn 50001
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll inv2=500000004ll;
il int read(){
	char c;int x=0,f=0;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))x=(x*10)+(c^48),c=getchar();
	return f?-x:x;
}
int n,a[maxn],tot=0;
ll k,kth;
int trie[maxn*30][2],cnt[maxn*30];
int res[maxn*30][31]; // 以i为子树里,第k位是1的数的个数
il void insert(int id){
	int u=0;
	for(int i=30;i>=0;i--){
		int c=(a[id]>>i)&1;
		if(!trie[u][c])trie[u][c]=++tot;
		u=trie[u][c],cnt[u]++;
		for(int k=0;k<=30;k++) 
			if((a[id]>>k)&1)res[u][k]++;
	}
}
il ll check(ll x){
	ll tot=0;
	for(int i=1;i<=n;i++){
		int u=0;
		for(int j=30;j>=0;j--){	
			int c1=(a[i]>>j)&1,c2=(x>>j)&1;
			if(c2)u=trie[u][c1^1];
			else tot+=cnt[trie[u][c1^1]],u=trie[u][c1];
			if(!u)break;
		}
		tot+=cnt[u];
	}
	return tot/2;
}
ll ans=0;
il void calc(){
	for(int i=1;i<=n;i++){
		int u=0;
		for(int j=30;j>=0;j--){
			int c1=(a[i]>>j)&1,c2=(kth>>j)&1;
			if(c2)u=trie[u][c1^1];
			else{
				for(int k=0;k<=30;k++){
					int c3=(a[i]>>k)&1;
					if(c3)ans=(ans+(1ll<<k)*(cnt[trie[u][c1^1]]-res[trie[u][c1^1]][k])%mod)%mod;
					else ans=(ans+(1ll<<k)*res[trie[u][c1^1]][k]%mod)%mod;
				}
				u=trie[u][c1];
			}
			if(!u)break;
		}
		ans=(ans+cnt[u]*1ll*kth%mod)%mod;
	}
	ans=(ans*inv2)%mod,ans=((ans-(check(kth)-k)*kth%mod)%mod+mod)%mod;
}
int main(){
	n=read(),k=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
		insert(i);
	}
	ll lt=0,rt=(1ll<<30)+1;
	while(lt+1<rt){
		ll mid=(lt+rt)>>1;
		if(check(mid)>=k)lt=mid;
		else rt=mid;
	}
	kth=lt,calc();
	printf("%lld\n",ans);
	return 0;
}

标签:int,ll,mid,tot,trie,CF241B,Friends,c1
From: https://www.cnblogs.com/blueparrot/p/17922241.html

相关文章

  • P8907 [USACO22DEC] Making Friends P 题解
    明明看着不难的题目,却意外的卡人。思路考虑两头奶牛可以成为朋友条件是什么。存在一条路径连接这两头奶牛。且除去端点外的路径上的所有点的编号小于两端点的较小值。充分必要性都比较显然。如何维护。我们可以从小到大加入点,维护这些路径。对于每个点维护一个\(\text{se......
  • B. Hossam and Friends
    B.HossamandFriends题目大意:有\(n\)对朋友,其中\(m\)对朋友互相不认识,让你选区间,最多可以选多少区间,区间中没有互相不认识的朋友思路:遍历每个点作为区间的左端点,必须满足\(a[i]\lea[i+1]\)(\(a[i]\)存储以\(i\)做左端点,右端点的最大值),证明:即前一项的右端点不可能比这一项......
  • 类、事件与对象---Dad&Mom&Friends(进阶事件)
    接上一个笔记:https://www.cnblogs.com/StephenYoung/p/17792668.html现在增加了一个新的朋友类:Friends这个类构造如下:从上到下依次是:1、字段名称、2、要离开的事件、3、方法--离开主人家、4、Friends构造函数(方法)、5、属性---体重、6、方法--感谢、7、方法--吃席、Fri......
  • [ABC245G] Foreign Friends 题解
    [ABC245G]ForeignFriends题解想法考虑所有颜色相同的弱化版。这种情况下,只需要把所有特殊点都推入队列之后跑多源Dijkstra即可。思路正解与上述做法大致相同。如果有颜色限制,那么可以考虑这个神仙思路:把所有特殊点的颜色用二进制表示,对于每一位,这一位是\(0\)的特殊......
  • 【后缀自动机】Codeforces Round #305 (Div. 1) E. Mike and Friends
    对所有的串加特殊字符隔开,单串建立后缀自动机。然后将每个的fa边反向建树,对树dfs得到dfs序,对dfs序建立线段树。询问离线,每个询问拆成1-(l-1)和1-r。。。按端点排序,然后每次加入线段树,查询k对应的节点的子树和。。。#include<iostream>#include<queue>#include<stack>#include......
  • CodeTON Round 5 (Div. 1 + Div. 2, Rated, Prizes!) D. Tenzing and His Animal Fri
    题面是真的抽象,翻译为人话之后大概就是,对于每个选择的集合当中,1必须选,n一定不能选,每个限制条件的意思是如果u和v不在一个集合里则最能玩y时间,则u或v独自玩最多玩y时间如果在同一集合则可以玩无限时间因此如果n和1不连通的话则一定为inf,否则的话就一定有限制,因为n一定不能选,则和......
  • About me & Friendship links
    Arsenetang https://arsenetang.github.ioeeee http://eeeeeeeeeeeeeeeea.cnFmyyy https://fmyyy1.github.ioLe1a https://www.le1a.comnnnpc https://nnnpc.github.ioo3Ev http://blog.o3ev.cnPl1rry https://www.pllrry.siteSiebene@ https://yao-mou.gitee.io......
  • CF547E Mike and Friends题解
    题目链接温馨提示:做本题之前可以先尝试这个:洛谷P2414阿狸的打字机(是简单版的uwu)。首先,这个题涉及多模式串匹配,首先想AC自动机。但是有个问题:我们如何去计算一个串出现的次数呢?我们先考虑查询一个串\(a\)在串\(b\)中出现的次数。首先,在AC自动机上有一个性质,就是如果......
  • ZOJ 3960 What Kind of Friends Are You?(模拟)
    传送门给你几个人,然后下i行对应的是回答出来第i个问题的人,最后询问回答出来了哪几个问题的是谁。用一个map,存名字和数字,回答出的问题编号也转化为2进制,然后转化为10进制,这样的话每个人回答出的问题就对应的是一个数字,询问的时候也把2进制的串转化为10进制,这样的话比对就比较方便。......
  • [ABC131E] Friendships
    2023-01-30题目传送门翻译难度&重要性(1~10):题目来源AtCoder题目算法找规律,构造解题思路先构造一个菊花图为最大边的图,再依次连边减小k。完成状态已完成......