noip模拟74(待补)

A. 自然数

线段树二分在之前的题目中出现过,但是我是用别的方法写的.

所以这个题在我这里就死了.

固定左端点应该是能想到的,因为这样的套路很多,但是自己没想到,不应该.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long 
	#define ull unsigned ll
	#define lf long double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		ll w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:-w;
	}
} using namespace BSS;

#define ls (x<<1)
#define rs (x<<1|1)
const ll N=1e6+21,W=2e5+21;

ll m,n,ans;
ll vis[N],val[N],lst[N],nxt[N];
struct I { ll sum,lzy,maxw; } tr[N<<2];
auto getval=[](ll 
x,ll w,ll l,ll r){ 
	tr[x].sum=(r-l+1)*w,tr[x].lzy=w,tr[x].maxw=w;
};
auto spread=[](ll x,ll l,ll r){
	ll &lzy=tr[x].lzy,mid=(l+r)>>1;
	if(~lzy) getval(ls,lzy,l,mid),getval(rs,lzy,mid+1,r),lzy=-1;
};
auto pushup=[](ll x){ 
	tr[x].sum=tr[ls].sum+tr[rs].sum;
	tr[x].maxw=max(tr[ls].maxw,tr[rs].maxw); 
};
void change(ll x,ll l,ll r,ll ql,ll qr,ll w){
	if(l>=ql and r<=qr) return getval(x,w,l,r),void();
	ll mid=(l+r)>>1; spread(x,l,r);
	if(ql<=mid) change(ls,l,mid,ql,qr,w);
	if(qr>mid) change(rs,mid+1,r,ql,qr,w);
	pushup(x);
}
ll qsum(ll x,ll l,ll r,ll ql,ll qr){
	if(l>=ql and r<=qr) return tr[x].sum;
	ll mid=(l+r)>>1,res=0; spread(x,l,r);
	if(ql<=mid) res+=qsum(ls,l,mid,ql,qr);
	if(qr>mid) res+=qsum(rs,mid+1,r,ql,qr);
	pushup(x); return res;
}
ll qmax(ll x,ll l,ll r,ll ql,ll qr){
	if(ql>qr) return -1;
	if(l>=ql and r<=qr) return tr[x].maxw;
	ll mid=(l+r)>>1,res=0; spread(x,l,r);
	if(ql<=mid) res=max(res,qmax(ls,l,mid,ql,qr));
	if(qr>mid) res=max(res,qmax(rs,mid+1,r,ql,qr));
	pushup(x); return res;
}
ll qpos(ll x,ll l,ll r,ll ql,ll qr,ll w){
	if(l==r) return tr[x].maxw>=w ? l : -1;
	ll mid=(l+r)>>1,res; spread(x,l,r);
	if(l>=ql and r<=qr){
		if(tr[ls].maxw>=w) res=qpos(ls,l,mid,ql,qr,w);
		else res=qpos(rs,mid+1,r,ql,qr,w);
		pushup(x); return res;
	}
	if(ql<=mid and tr[ls].maxw>w) res=qpos(ls,l,mid,ql,qr,w);
	else res=qpos(rs,mid+1,r,ql,qr,w);
	pushup(x); return res;
}
void build(ll x,ll l,ll r){
	tr[x].lzy=-1;
	if(l==r) return ; ll mid=(l+r)>>1;
	build(ls,l,mid),build(rs,mid+1,r);
}
signed main(){
	File(mex);
	n=read();  ll now=0,x,y;
	for(ll i=1;i<=n;i++) val[i]=read();
	for(ll i=1;i<=n;i++){
		if(val[i]>n) { change(1,1,n,i,i,now); continue; }
		if(vis[val[i]]) lst[i]=vis[val[i]],nxt[vis[val[i]]]=i; 
		vis[val[i]]=i; while(vis[now]) now++; change(1,1,n,i,i,now);
	}
	for(ll i=n;i>=1;i--){
		if(val[i]>n) continue;
		if(!nxt[i]) nxt[i]=n+1;
	}
	for(ll i=1;i<=n;i++){
		ans+=qsum(1,1,n,i,n);
		if(val[i]>n or qmax(1,1,n,i+1,n)<val[i]) continue;
		now=qpos(1,1,n,i+1,n,val[i]);
		if(now>0) change(1,1,n,now,nxt[i]-1,val[i]);
	}
	printf("%lld\n",ans),exit(0);
}

B. 钱仓

签到题,贪心乱写.

由于博主比较智障,直接糊了个线段树.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long 
	#define ull unsigned ll
	#define lf long double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		ll w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:-w;
	}
} using namespace BSS;

#define ls x<<1
#define rs x<<1|1
const ll N=2e5+21,inf=1e15;

ll m,n,pc,ans,minpos,minval;
ll o[N];
struct I { ll w,c,len,lc,llen; } tr[N<<2];
auto getval=[](ll x,ll c,ll len)->void{
	tr[x].c+=c,tr[x].len+=len,tr[x].w=tr[x].len-tr[x].c;
	tr[x].lc+=c,tr[x].llen+=len;
};
void update(ll x,ll l,ll r,ll ql,ll qr,ll c,ll len){
	if(l>=ql and r<=qr) return getval(x,c,len)/*,cout<<l<<' '<<r<<" "<<tr[x].c<<' '<<tr[x].w<<endl*/,void();
	 // 让 len-c 时刻都 >= 0 ,所以维护最小值,如果存在最小值小于 0,那么不行.
	ll mid=(l+r)>>1; 
	getval(ls,tr[x].lc,tr[x].llen),getval(rs,tr[x].lc,tr[x].llen);
	tr[x].lc=0,tr[x].llen=0;
	if(ql<=mid) update(ls,l,mid,ql,qr,c,len);
	if(qr>mid) update(rs,mid+1,r,ql,qr,c,len);
	ll y= (tr[ls].w<tr[rs].w ? ls : rs);
	tr[x].w=tr[y].w,tr[x].c=tr[y].c,tr[x].len=tr[y].len;
	// cout<<l<<' '<<r<<' '<<tr[x].w<<' '<<tr[ls].w<<' '<<tr[rs].w<<endl;
}
signed main(){
	File(barn);
	n=read(),m=n<<1,minval=inf; ll flag=0,res;
	for(ll i=1;i<=n;i++){
		o[i]=read(),o[i+n]=o[i],flag|=(o[i]==0);
	}
	for(ll i=m;i>=n+1;i--) pc+=o[i],update(1,1,m,i,i,pc,m-i+1);
	for(ll i=1;i<=n;i++) update(1,1,m,i,i,-inf,inf);
	if(!flag) puts("0"),exit(0); minval=tr[1].w,minpos=m;
	for(ll i=n;i>=2;i--){
		update(1,1,m,i+n,i+n,-inf,inf);
		ll r=i+n-1,l=i-1;
		update(1,1,m,l,r,-o[r+1],-1),update(1,1,m,i,i,pc,n);
		if(tr[1].w>minval) minval=tr[1].w,minpos=i+n-1;
	}
	// cout<<minval<<' '<<minpos<<endl;
	for(ll i=minpos,j=minpos;i>=minpos-n+1;i--){
		if(!o[i]){
			while(!o[j]) j--;
			o[i]++,o[j]--,ans+=(i-j)*(i-j);
		}
		else j=min(j,i-1);
	}
	printf("%lld\n",ans),exit(0);
}

C. 游戏

很明显应该是 \(dp\),很明显又应该是矩阵优化.

其实列个式子好像就很容易出来了,感觉并不是那种完全做不出来的题目。

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long 
	#define ull unsigned ll
	#define lf long double
	#define lbt(x) (x&(-x))
	#define mp(x,y) make_pair(x,y)
	#define lb lower_bound 
	#define ub upper_bound
	#define Fill(x,y) memset(x,y,sizeof x)
	#define Copy(x,y) memcpy(x,y,sizeof x)
	#define File(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read() {
		ll w=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) w=(w<<3)+(w<<1)+(ch^48),ch=getchar();
		return cit?w:-w;
	}
} using namespace BSS;

const ll mod=1e9+7;

ll n,p,q,m,Ts;
ll f[3],g[3][3],g1[3][3],g2[3][3];
auto ksm=[](ll a,ll b,ll c)->ll{
	ll res=1; a%=c;
	for(;b;b>>=1,a=a*a%c) if(b&1) res=res*a%c;
	return res%c;
};
inline void mul(){
	ll c[3]={0};
	for(ll j=1;j<=2;j++){
		for(ll k=1;k<=2;k++)
			c[j]=(c[j]+f[k]*g[k][j]%mod)%mod;
	}
	Copy(f,c);
}
inline void mulself(){
	ll c[3][3]={0};
	for(ll i=1;i<=2;i++){
		for(ll j=1;j<=2;j++)
			for(ll k=1;k<=2;k++)
				c[i][j]=(c[i][j]+g[i][k]*g[k][j]%mod)%mod;
	}
	Copy(g,c);
}
inline void mulmore(){
	ll c[3]={0};
	for(ll j=1;j<=2;j++){
		for(ll k=1;k<=2;k++)
			c[j]=(c[j]+f[k]*g2[k][j]%mod)%mod;
	}
	Copy(f,c);
}
signed main(){
	File(game);
	Ts=read();
	while(Ts--){
		Fill(f,0),Fill(g,0);
		ll x=ksm(1e8,mod-2,mod); f[2]=1;
		n=read(),p=read()%mod*x%mod,q=read()%mod*x%mod;
		x=ksm(1-p*q%mod+mod,mod-2,mod);
		g1[1][1]=p*(1-q+mod)%mod*x%mod,g1[2][1]=(1-p+mod)*x%mod;
		g1[1][2]=(1-q+mod)*x%mod,g1[2][2]=q*(1-p+mod)%mod*x%mod;	
		x=ksm(1-(1-p+mod)%mod*(1-q+mod)%mod+mod,mod-2,mod);
		g2[1][1]=(1-p+mod)*q%mod*x%mod,g2[2][1]=p*x%mod;
		g2[1][2]=q*x%mod,g2[2][2]=(1-q+mod)*p%mod*x%mod;
		for(ll i=1;i<=2;i++){
			for(ll j=1;j<=2;j++)
				for(ll k=1;k<=2;k++)
					g[i][j]=(g[i][j]+g2[i][k]*g1[k][j]%mod)%mod;
		}
		m=n>>1; for(;m;m>>=1,mulself()) if(m&1) mul();
		if(n&1) mulmore();
		printf("%lld\n",f[1]);
	}
	exit(0);
}

D. Sanrd

没改,先鸽.

上一篇:CF1017G The Tree


下一篇:Subsequence HDU - 3530