noip模拟74

T1

指针扫左端点,此时mex值随右端点递增

考虑左指针移动,也就是删一个值x,贡献是mex刚开始大于x的位置,到x下一次在序列中出现的位置-1,mex全部覆盖为x

线段树区间修改,区间二分值

T2

必定存在某个位置的1不动

考虑枚举这个位置,然后断环为链,记位置i值为\(a_i\)\(sum_i=\sum_{j=1}^{i}a[i]\)\(sum0_i=\sum_{j=1}^{i}[a_i=0]\)

若此时能够造成贡献,满足\(\forall k\in[1,n],sum_i-1-sum0_i>=0\),因为只有前面的1才能放到后面

贡献就贪心地将最后边的1放到最后的0的位置,因为\(a^2+b^2<=(a+b)^2\)

当然这样可能是\(O(n^2)\)的,因为被卡了

两个剪枝

  1. 搜索合法位置时,若枚举到\(a_i=1\),直接跳过,因为计算合法性有一个\(sum_i-1\),此时\(a_i=1\)没贡献。事实证明这样的剪枝是非常有效的,TLE的代码加上这句话就900msA了,最慢的点229ms

  2. 枚举到合法位置直接计算贡献然后return。不会证明,但是加上后就900ms变300msA

T3

剩奇数个数都希望拿到正面,偶数反之

\(a_i\)表示剩i个球时Alice先手赢的概率,\(b_i\)表示剩i个球时Bob先手赢的概率

若i为奇数,\(a_{i+1}=p* b_i+(1-p)* q* a_i+(1-p)* (1-q) *a_{i+1}\)

化简一下,\(a_{i+1}=\frac{p* b_i+(1-p)* q* a_i}{p+q-p* q}\)

偶数时就是把p换成1-p,q换成1-q

b的方程同理

代码

T1

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+11;
struct tree{
	int l,r;
	int minn;
	int sum;
	int lazy;
}tre[4*N];
int n;
int ans;
int ton[N];
int a[N],lsh[N];
int nxt[N],last[N];
inline int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0') ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;
}
inline int min_(int x,int y){return x>y?y:x;}
void lsh_()
{
	sort(lsh+1,lsh+n+1);
	int x=unique(lsh+1,lsh+n+1)-lsh;
	for(int i=1;i<=n;i++) a[i]=lower_bound(lsh+1,lsh+x,a[i])-lsh;
	return;
}
void build(int i,int l,int r)
{
	tre[i].lazy=-1;
	tre[i].l=l;
	tre[i].r=r;
	if(l==r) return;
	int mid=(l+r)>>1;
	build(i<<1,l,mid);
	build(i<<1|1,mid+1,r);
	return;
}
inline void js(int i){tre[i].sum=(tre[i].r-tre[i].l+1)*tre[i].minn;}
inline void pushdown(int i)
{
	if(tre[i].l==tre[i].r) return;
	tre[i<<1].lazy=tre[i<<1].minn=tre[i].lazy;
	tre[i<<1|1].lazy=tre[i<<1|1].minn=tre[i].lazy;
	js(i<<1);js(i<<1|1);
	tre[i].lazy=-1;
	return;
}
inline void update(int i)
{
	tre[i].sum=tre[i<<1].sum+tre[i<<1|1].sum;
	tre[i].minn=min_(tre[i<<1].minn,tre[i<<1|1].minn);
	return;
}
void insert(int i,int x,int sum)
{
	if(tre[i].lazy!=-1) pushdown(i);
	if(tre[i].l==tre[i].r){tre[i].minn=tre[i].sum=sum;return;}
	int mid=(tre[i].l+tre[i].r)>>1;
	if(x<=mid) insert(i<<1,x,sum);
	else insert(i<<1|1,x,sum);
	update(i);
	return;
}
int query(int i,int x)
{
	if(tre[i].lazy!=-1) pushdown(i);
	if(tre[i].l==tre[i].r)
	{
		if(tre[i].sum>=x) return tre[i].l;
		return n+1;
	}
	int mid=(tre[i].l+tre[i].r)>>1;
	if(tre[i<<1|1].minn<x) return query(i<<1|1,x);
	else return min_(query(i<<1,x),tre[i<<1|1].l);
	return n+1;
}
void change(int i,int l,int r,int x)
{
	if(tre[i].lazy!=-1) pushdown(i);
	if(tre[i].l>=l&&tre[i].r<=r)
	{
		tre[i].minn=x;
		tre[i].sum=x*(tre[i].r-tre[i].l+1);
		tre[i].lazy=x;
		return;
	}
	int mid=(tre[i].l+tre[i].r)>>1;
	if(l<=mid) change(i<<1,l,r,x);
	if(r>mid) change(i<<1|1,l,r,x);
	update(i);
	return;
}
signed main()
{
	FILE* x=freopen("mex.in","r",stdin);
	x=freopen("mex.out","w",stdout);
	n=read();
	for(int i=1;i<=n;++i) lsh[i]=a[i]=read();
	lsh_();
	for(int i=1;i<=n;++i)
	{
		nxt[last[a[i]]]=i;
		last[a[i]]=i;
	}
	build(1,1,n);
	for(int i=1;i<=n;++i) if(!nxt[i]) nxt[i]=n+1;
	int r=0;
	for(int i=1;i<=n;++i)
	{
		if(lsh[a[i]]<=n) ton[lsh[a[i]]]++;
		while(ton[r]) ++r;
		insert(1,i,r);
	}
	ans+=tre[1].sum;
	for(int nw,nx,i=1;i<n;++i)
	{
		nx=nxt[i]-1;
		insert(1,i,0);
		nw=query(1,lsh[a[i]]+1);
		if(nx>=nw) change(1,nw,nx,lsh[a[i]]);
		ans+=tre[1].sum;
	}
	cout<<ans<<endl;
	return 0;
}

T2

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+11;
int n;
int a[N];
int tem[N];
vector<int> vct;
inline int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0') ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;
}
inline int min_(int x,int y){return x>y?y:x;};
signed main()
{
	FILE* x=freopen("barn.in","r",stdin);
	x=freopen("barn.out","w",stdout);
	bool jd=1;
	n=read();
	for(int i=1;i<=n;++i) jd&=((a[i]=a[i+n]=read())==1);
	if(jd){cout<<0<<endl;return 0;};
	for(int i=1;i<=n;i++)
	{
		if(a[i]==1) continue;
		bool jd=1;
		int sum0=0,suma=0;
		for(int j=i;j<n+i;++j)
		{
			if(!a[j]) ++sum0;
			else suma+=a[j]-1;
			if(suma-sum0<0) {jd=0;break;}
		}
		if(!jd) continue;
		vct.push_back(i);
		
	}
	long long ans=1e18;
	for(int i=0;i<vct.size();i++)
	{
		long long sum=0;
		int st=vct[i];
		memcpy(tem+1,a+st,sizeof(int)*n);
		int p1=n;
		while(tem[p1]) --p1;
		int p2=p1;
		while(1)
		{
			while(p2>=p1||!tem[p2]) --p2;
			--tem[p2];
			tem[p1]=1;
			sum+=1ll*(p1-p2)*(p1-p2);
			while(p1>0&&tem[p1]) --p1;
			if(p1==0) break;
			while(p2>=p1||!tem[p2]) --p2;
		}
		ans=min_(ans,sum);
	
	}
	cout<<ans<<endl;
	return 0;
}

T3

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int inv=571428574;
const int mod=1e9+7;
struct mat_{
	int h,l;
	int mat[4][4];
	friend mat_ operator*(mat_ a,mat_ b)
	{
		mat_ c;
		memset(&c,0,sizeof(c));
		for(int i=1;i<=a.h;++i)
			for(int k=1;k<=b.h;++k)
			{
				if(a.mat[i][k]==0) continue;
				for(int j=1;j<=b.l;++j)
					c.mat[i][j]=(c.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
			}
		c.h=a.h;
		c.l=b.l;
		return c;
	}
}ans,x1,x2,x;
int p,q,n;
inline int read()
{
	int s=0;
	char ch=getchar();
	while(ch>'9'||ch<'0') ch=getchar();
	while(ch>='0'&&ch<='9')
	{
		s=(s<<1)+(s<<3)+(ch^48);
		ch=getchar();
	}
	return s;
}
int fm(int xx,int y)
{
	int as=1;
	while(y)
	{
		if(y&1) as=as*xx%mod;
		xx=xx*xx%mod;
		y>>=1;
	}
	return as;
}
void solve()
{
	int pq=fm((1+mod-p*q%mod),mod-2);
	int pq2=fm((p+q-p*q%mod+mod)%mod,mod-2);

	x1.h=x2.l=x1.l=x2.h=2;

	x1.mat[1][1]=(mod+1-p)*q%mod*pq2%mod;
	x1.mat[2][1]=p*pq2%mod;
	x1.mat[1][2]=q*pq2%mod;
	x1.mat[2][2]=(1-q+mod)*p%mod*pq2%mod;

	x2.mat[1][1]=(1-q+mod)*p%mod*pq%mod;
	x2.mat[2][1]=(1-p+mod)*pq%mod;
	x2.mat[1][2]=(1-q+mod)*pq%mod;
	x2.mat[2][2]=(1-p+mod)*q%mod*pq%mod;

	x=x1*x2;

	memset(&ans,0,sizeof(ans));
	ans.h=2,ans.l=2;
	ans.mat[1][1]=1;
	ans.mat[2][2]=1;
	int y=n/2;
	while(y)
	{
		if(y&1) ans=ans*x;
		x=x*x;
		y>>=1;
	}
	return;
}
signed main()
{
	FILE* x=freopen("game.in","r",stdin);
	x=freopen("game.out","w",stdout);
	int t=read();
	while(t--)
	{
		n=read();
		p=read()*inv%mod;
		q=read()*inv%mod;
		solve();
		mat_ anss;
		memset(&anss,0,sizeof(anss));
		anss.h=1,anss.l=2;
		anss.mat[1][1]=0;
		anss.mat[1][2]=1;
		if(n&1) ans=ans*x1;
		anss=anss*ans;
		cout<<anss.mat[1][1]<<endl;
	}
	return 0;
}
posted @ 2021-10-17 07:17  sitiy  阅读(15)  评论(0编辑  收藏  举报