博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

8.22 附加赛4


2018.8.22 附加赛4(HEOI2018模拟赛)

时间:3h+(实际)
期望得分:100+10+0
实际得分:100+10+0

比赛链接

BC毒瘤啊 暴力也没什么好写的

A 立体几何题(线段树 动态开点/树状数组)

题目链接

  就是求\(\sum_{i=1}^n\sum_{j=1}^n\min(A[i],B[j])\)。同时有\(m\)次单个元素修改。
  当然不能直接算。考虑每个数会被算多少次:$$Ans=\sum_{i=1}nA[i]\times\sum_{j=1}n[A[i]\leq B[j]]+\sum_{i=1}nB[i]\times\sum_{j=1}n[B[i]<A[j]]$$
  这用树状数组维护就可以了。
  至于修改,因为每次只改一个元素,比如改\(A[i]\),只可能影响到它对\(n\)\(B[\ ]\)的贡献和\(n\)\(B[\ ]\)对它的贡献。这个区间查一下个数和\(B[\ ]\)的区间和就行了。然后单点修改\(A[i]\)
  动态开点的值域线段树或是离散化后树状数组都行,后者常数更优。
  不卡空间也不强制在线的话就没必要上平衡树了。

#include <cstdio>
#include <cctype>
#include <algorithm>
//#define gc() getchar()
#define MAXIN 300000
#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=200005*28;//log(1e8)!

int n,A[100005],B[100005];
char IN[MAXIN],*SS=IN,*TT=IN;

struct Segment_Tree
{
	#define lson son[x][0]
	#define rson son[x][1]
	int tot,son[N][2],sz[N];
	LL sum[N];

	#define Update(x) sum[x]=sum[lson]+sum[rson], sz[x]=sz[lson]+sz[rson]
	void Insert(int &x,int l,int r,int pos)
	{
		if(!x) x=++tot;
		if(l==r)
		{
			++sz[x], sum[x]+=pos;
			return;
		}
		int m=l+r>>1;
		if(pos<=m) Insert(lson,l,m,pos);
		else Insert(rson,m+1,r,pos);
		Update(x);
	}
	void Delete(int x,int l,int r,int pos)
	{
		if(!x) return;//x=++tot;
		if(l==r)
		{
			--sz[x], sum[x]-=pos;
			return;
		}
		int m=l+r>>1;
		if(pos<=m) Delete(lson,l,m,pos);
		else Delete(rson,m+1,r,pos);
		Update(x);
	}
	LL Query_Sum(int x,int l,int r,int L,int R)
	{
		if(!sz[x]) return 0;
		if(L<=l && r<=R) return sum[x];
		int m=l+r>>1;
		if(L<=m)
			if(m<R) return Query_Sum(lson,l,m,L,R)+Query_Sum(rson,m+1,r,L,R);
			else return Query_Sum(lson,l,m,L,R);
		return Query_Sum(rson,m+1,r,L,R);
	}
	int Query_Num(int x,int l,int r,int L,int R)
	{
		if(!sz[x]) return 0;
		if(L<=l && r<=R) return sz[x];
		int m=l+r>>1;
		if(L<=m)
			if(m<R) return Query_Num(lson,l,m,L,R)+Query_Num(rson,m+1,r,L,R);
			else return Query_Num(lson,l,m,L,R);
		return Query_Num(rson,m+1,r,L,R);
	}
}TA,TB;

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}

int main()
{
//	freopen("ex_graph3.in","r",stdin);
//	freopen("graph.out","w",stdout);

	#define R 100000001
	#define SA RTA,0,R//from 0!
	#define SB RTB,0,R
	n=read(); int RTA=0, RTB=0;
	for(int i=1; i<=n; ++i) TA.Insert(SA,A[i]=read());
	for(int i=1; i<=n; ++i) TB.Insert(SB,B[i]=read());
	LL Ans=0;
	for(int i=1; i<=n; ++i) Ans+=1ll*A[i]*TB.Query_Num(SB,A[i],R);
	for(int i=1; i<=n; ++i) Ans+=1ll*B[i]*TA.Query_Num(SA,B[i]+1,R);
	printf("%lld\n",Ans);
	for(int m=read(),opt,i,bef,nxt; m--; )
	{
		opt=read(), i=read(), nxt=read();
		if(!opt)
		{
			bef=A[i];
			Ans+=1ll*nxt*TB.Query_Num(SB,nxt,R)-1ll*bef*TB.Query_Num(SB,bef,R);
			if(bef<nxt) Ans+=TB.Query_Sum(SB,bef,nxt-1);
			else if(bef>nxt) Ans-=TB.Query_Sum(SB,nxt,bef-1);
			TA.Delete(SA,bef), TA.Insert(SA,nxt), A[i]=nxt;
		}
		else
		{
			bef=B[i];
			Ans+=1ll*nxt*TA.Query_Num(SA,nxt+1,R)-1ll*bef*TA.Query_Num(SA,bef+1,R);
			if(bef<nxt) Ans+=TA.Query_Sum(SA,bef+1,nxt);
			else if(bef>nxt) Ans-=TA.Query_Sum(SA,nxt+1,bef);
			TB.Delete(SB,bef), TB.Insert(SB,nxt), B[i]=nxt;
		}
		printf("%lld\n",Ans);
	}
	return 0;
}

B 仙人掌毒题(容斥/分治NTT 期望)

题目链接

弃疗


C 珂学计树题(Burnside)

题目链接

弃疗


考试代码

B

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define mod (998244353)
const int N=1e5+5,M=2e5+5;

int n,m,T,W,fa[N];

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}
int Get_fa(int x){
	return x==fa[x]?x:fa[x]=Get_fa(fa[x]);
}

int main()
{
//	freopen("ex_cactus2.in","r",stdin);
//	freopen(".out","w",stdout);

	n=read(), m=read(), T=read(), W=read();
	for(int i=1; i<=n; ++i) fa[i]=i;
	int ans=n;
	for(int u,v; m--; )
	{
		u=read(), v=read();
		if(Get_fa(u)!=Get_fa(v)) fa[fa[u]]=v, --ans;
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2018-08-22 22:03  SovietPower  阅读(106)  评论(0编辑  收藏  举报