ZROI Day1 比赛解题报告

ZROI Day1 比赛解题报告

版权原因不提供题面相关信息


前天晚上搞得比较晚,然后早上做题很没状态,刚看到T1发现没什么思路就有点慌,赶紧看了看T2,T3,
发现T3暴力很好打,T2想了一想可以用数据结构维护一个贪心(感觉我比较能乱搞的只有数据结构)然后码码码,回来看T1还是没什么感觉,随手打了30pts暴力....然后就写炸了,90-->60,真的太菜了

A

现在看确实像是提高难度,有几个显然的性质考场上全都没想到...

  1. 若用(bit(x))表示x在二进制下1的个数,则(bit(x) (xor) (y) \%2=(bit(x)+bit(y))\%2)

  2. 对于区间([0,m]),其中二进制下1的个数为偶数的数的个数x为

    • ((m+1)/2) ---m为奇数
    • (m/2-1+[m)有偶数个(1]) ---m为偶数

所以只要把区间离散化后统计答案即可,对于一个区间,其中的对数为二进制下有奇数个1的数的个数乘以二进制下有偶数个1的数的个数

B

这题也需要几个性质,很容易手推得到做出的贡献是单调的,于是有个朴素的做法是对于每一个偶数数组,我们枚举此时在它后面插入每一个奇数对答案的贡献,即产生的逆序对,然后取各个的最小值加起来,当然要先预处理加在第一个数前面的情况,时间复杂度(O(N) (log) (N))

正解其实与上面类似,然而我们是枚举每一个奇数,用数据结构维护它的最优贡献

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
#define ll long long 
#define ri register int 
using std::min;
template <class T>inline void read(T &x){
	x=0;int ne=0;char c;
	while(!isdigit(c=getchar()))ne=c=='-';
	x=c-48;
	while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
	x=ne?-x:x;return ;
}
const int maxn=200005;
const int inf=0x7fffffff;
int n;
int a[maxn],pos[maxn];
int L,R,dta;
struct Segment_Tree{
	int mi[maxn<<2],tag[maxn<<2];
	void build(int now,int l,int r){
	mi[now]=inf,tag[now]=0;
		if(l==r){
			mi[now]=l;
			return ;
		}
		int mid=(l+r)>>1;
		build(now<<1,l,mid);
		build(now<<1|1,mid+1,r);
		mi[now]=min(mi[now<<1],mi[now<<1|1]);
		return ;
	}
	inline void pushdown(int now){
		if(tag[now]!=0){
	    mi[now<<1]+=tag[now];
		mi[now<<1|1]+=tag[now];
		tag[now<<1]+=tag[now];
		tag[now<<1|1]+=tag[now];
		tag[now]=0;
		}
		return ;
	} 
	void update(int now,int l,int r){
		if(L<=l&&r<=R){
			mi[now]+=dta;
			tag[now]+=dta;
			return ;
		}
		int mid=(l+r)>>1;
		pushdown(now);
		if(L<=mid)update(now<<1,l,mid);
		if(mid<R)update(now<<1|1,mid+1,r);
		mi[now]=min(mi[now<<1],mi[now<<1|1]);
		return ;
	}
	int query(int now,int l,int r){
		if(L<=l&&r<=R){
			return mi[now];
		}
		int mid=(l+r)>>1,ans=inf;
		pushdown(now);
		if(L<=mid)ans=min(ans,query(now<<1,l,mid));
		if(mid<R)ans=min(ans,query(now<<1|1,mid+1,r));
		mi[now]=min(mi[now<<1],mi[now<<1|1]);
		return ans;
	}
}T;
struct BIT{
    int b[maxn];
	inline void add(int x,int y){
		for(ri i=x;i<=y;i+=(i&-i)){
			b[i]++;
		}
		return ;
	}
	inline int get(int x){
		int ans=0;
		for(ri i=x;i>0;i-=(i&-i)){
			ans+=b[i];
		}	
		return ans;
	}	
}B;
int main(){
	ll ans=0;
	read(n);
	n=n>>1;
	for(ri i=1;i<=n;i++){
		read(a[i]);
		pos[a[i]]=i;
	}
	for(ri i=n;i>=1;i--){
		ans+=B.get(a[i]);
		B.add(a[i],n<<1);
	}	
	T.build(1,0,n);
	for(ri i=1;i<=n;i++){
		L=0,R=n;
		ans+=T.query(1,0,n);//printf("%d
",ans);
		int x=pos[i*2];
		L=0,R=x-1,dta=1;
		T.update(1,0,n);
		L=x,R=n,dta=-1;
		T.update(1,0,n);
	}
	printf("%lld
",ans);
	return 0;
}

C

三重容斥,毒瘤

原文地址:https://www.cnblogs.com/Rye-Catcher/p/9420852.html