人,只有自己站起来,这个世界才能属于他。|

园龄:粉丝:关注:

abc392 题解合集

here.

perf:2341

草忘写了,赶紧补档。

E

这种题都能被放到 E 了吗。

考虑最小化答案为 cnt1cnt 是联通块个数。

考虑构造答案,首先把能加的边加上,然后用 set 和并查集维护当前联通块集合,对于之前没加过的边,能加就加。

总体复杂度 O(mlogn)

#include<bits/stdc++.h>
using namespace std;
int n,m,cnt,vis[200005];
struct node{
	int id,x,y;
}h[200005];
int fa[200005];
void init(){
	for(int i=1;i<=n;i++) fa[i]=i;
}
int find(int x){
	if(fa[x]==x) return x;
	else return fa[x]=find(fa[x]); 
}
void merge(int x,int y){
	x=find(x);
	y=find(y);
	fa[x]=y;
}
set<int> s;
vector<node> ans;
void add(int id,int x,int y){
	ans.push_back((node){id,x,y}); 
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0); 
	cin>>n>>m;
	init();
	for(int i=1;i<=m;i++){
		cin>>h[i].x>>h[i].y;
		if(find(h[i].x)==find(h[i].y)) continue;
		vis[i]=1;
		merge(h[i].x,h[i].y);
		cnt++;
	}
	for(int i=1;i<=n;i++){
		if(find(i)==i) s.insert(i);
	}
	for(int i=1;i<=m && cnt<n-1;i++){
		if(vis[i]) continue;
		if(s.find(find(h[i].x))==s.end()) continue;
		s.erase(find(h[i].x));
		merge(h[i].x,*s.begin());
		add(i,h[i].x,*s.begin());
		cnt++;
	}
	cout<<ans.size()<<'\n';
	for(int i=0;i<ans.size();i++){
		cout<<ans[i].id<<' '<<ans[i].x<<' '<<ans[i].y<<'\n';
	}
	return 0;
} 

F

出的还行。

考虑倒序加点,也就是按 n1 的顺序加点。

初始把所有位置设为 1,加一个点就把这个位置设为 0,寻找位置的过程可以轻松在线段树上二分求出。

总体复杂度 O(nlogn)

fun fact:如果看到这个题,你没有想到 FHQ,说明你的 OI 水平有提升!

#include<bits/stdc++.h>
using namespace std;
int n,p,a[500005],b[500005];
int val[1000005],ls[1000005],rs[1000005],dcnt,rt;
void pushup(int x){
	val[x]=val[ls[x]]+val[rs[x]];
}
void build(int l,int r,int &x){
	x=++dcnt;
	if(l==r){
		val[x]=1;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls[x]);
	build(mid+1,r,rs[x]);
	pushup(x);
}
void modify(int l,int r,int pos,int x){
	if(l==r){
		val[x]=0;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) modify(l,mid,pos,ls[x]);
	else modify(mid+1,r,pos,rs[x]);
	pushup(x);
}
int find(int l,int r,int k,int x){
	if(l==r) return l;
	int mid=(l+r)>>1;
	if(val[ls[x]]>=k) return find(l,mid,k,ls[x]);
	else return find(mid+1,r,k-val[ls[x]],rs[x]);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	build(1,n,rt);
	for(int i=n;i>=1;i--){
		p=find(1,n,a[i],rt);
		b[p]=i;
		modify(1,n,p,rt);
	}
	for(int i=1;i<=n;i++){
		cout<<b[i]<<' ';
	}
	return 0;
}

G

正常题吧。

但是大家是不是都是 poly 高手啊一眼秒。

首先将这个柿子移项:

A+C=2B

fi 表示 i=A+C 的二元组 (A,C) 个数,gi 表示集合中 i 这个数是否存在,那么不难得到:

fi=12j=0igjgij1

答案为:

ans=i=1|S|f2si

然后上面那个柿子是 gg 的形式,所以直接 fft。

总体复杂度 O(nlogn)

fan fact:有一个 saber 赛时怕贺错 fft,重敲了一遍 fft。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const double PI=acos(-1);
int n,m,k,s[1000005],ans,x,f[4000005];
struct node{
	double x,y;
	node(){
		x=y=0;
	}
	node(double a,double b){
		x=a,y=b;
	}
	node operator +(const node &a)const{
		return node(x+a.x,y+a.y);
	}
	node operator -(const node &a)const{
		return node(x-a.x,y-a.y);
	}
	node operator *(const node &a)const{
		return node(x*a.x-y*a.y,x*a.y+y*a.x);
	}
	node operator /(const double a)const{
		return node(x/a,y/a);
	}
}a[4000005],b[4000005];
void fft(node *a,int n){
	for(int i=1;i<n;i++){
		if(i<f[i]) swap(a[i],a[f[i]]); 
	}
	for(int len=2,m=1;len<=n;m=len,len<<=1){
	    node W=node(cos(1.0*PI/m),sin(1.0*PI/m)),w=node(1,0);
		for(int l=0,r=len-1;r<=n;l+=len,r+=len){
			node w0=w;
			for(int i=l;i<l+m;i++){
				node x=a[i]+w0*a[i+m],y=a[i]-w0*a[i+m];
				a[i]=x;
				a[i+m]=y;
				w0=w0*W;
			}
		}
	}
}
void solve(node *a,node *b,int n,int m){
	int l=log2(n+m)+1;
	int s=1<<l;
	for(int i=0;i<=s;i++){
		f[i]=(f[i>>1]>>1)|((i&1)<<(l-1));
	}
	fft(a,s);
	fft(b,s);
	for(int i=0;i<=s;i++){
		a[i]=a[i]*b[i];
	}
	fft(a,s);
	reverse(a+1,a+s);
	for(int i=0;i<=s;i++){
		a[i]=a[i]/s;
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>k;
	n=1e6;
	m=1e6;
	for(int i=1;i<=k;i++){
		cin>>s[i];
		a[s[i]]=node(1,0);
		b[s[i]]=node(1,0);
	}
	solve(a,b,n,m);
	for(int i=1;i<=k;i++){
		ans+=(int)(0.5+a[2*s[i]].x)-1;
	}
	cout<<ans/2;
	return 0;
}

本文作者:Kenma

本文链接:https://www.cnblogs.com/Kenma/p/18707448

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   _Kenma  阅读(19)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起