Loading

noip模拟67

A. 数据恢复

又一次徘徊于正解的边缘.

什么都可以想到,但偏是实现的方法不对.

本来可以直接用 \(set\) 的东西结果非要打线段树.

别的东西推推性质就行了.

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 res=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
		return cit?res:-res;
	}
} using namespace BSS;

const ll N=3e5+21;

ll m,n,ans,ts;
ll head[N],fa[N],tn[N],to[N],in[N];
multiset<pair<lf,ll> > s;
struct I { ll a,b; lf c; } p[N],bin[N];
ll find(ll x){ return x==fa[x] ? x : fa[x]=find(fa[x]); } 
inline void getc(ll x){ p[x].c=1.0*p[x].a/(1.0*p[x].b); }
inline void merge(ll x,ll y){
	ans+=p[y].b*p[x].a;
	p[y].a+=p[x].a,p[x].a=0;
	p[y].b+=p[x].b,p[x].b=0;
	getc(y),fa[find(x)]=find(y);
}
signed main(){
	File(data);
	n=read(); ll u,v,sum=0;
	for(int i=2;i<=n;i++) to[i]=read();
	for(int i=1;i<=n;i++){
		p[i].a=read(),p[i].b=read(),getc(i);
		s.insert(mp(p[i].c,i)),in[i]=1,fa[i]=i;
	}
	while(s.size()){
		auto it=s.begin();
		u=it->second,v=find(to[u]);
		s.erase(s.begin()),in[u]=0; 
		if(!to[u]) continue;
		if(in[v]){
			s.erase(s.find(mp(p[v].c,v)));
			merge(u,v);
			s.insert(mp(p[v].c,v));
		}
		else{
			merge(u,find(v));
		}
	}
	printf("%lld\n",ans);
	exit(0);
}

B. 下落的小球

感觉这个题目比 \(T1\) 更可做.

数学题,可以看成两个可重集排列来做.

第一个可重集排列:
考虑每个子树除了要落下自己的子树上的点之外,还要落下祖先上的点.
但是落到每棵子树上的祖先上的点的个数是固定的,只是落到不同子树的顺序不同.
所以这个时候可以给顺序写一个可重集排列.

第二个可重集排列:
每个子树在降落完祖先上的点之后,再去分别降落自己子树上面的点.
发现仍然只需要考虑各个子树的降落顺序.
再写一个可重集排列就行了.

最后两个方案数乘起来就是答案.

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 res=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0; 
		while(isdigit(ch)) res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
		return cit?res:-res;
	}
} using namespace BSS;

const ll N=1e6+21,mod=1e9+7;

ll m,n,ts,ans;
ll head[N],req[N],frc[N],siz[N],inv[N];
struct I { ll u,v,nxt; } e[N];
inline void add(ll u,ll v){
	e[++ts].u=u,e[ts].v=v,e[ts].nxt=head[u];
	head[u]=ts;
}
inline ll ksm(ll a,ll b,ll c){
	ll res=1; a%=c;
	for(;b;b>>=1,a=a*a%c) if(b&1) res=res*a%c;
	return res%c;
}
void dfs(ll u){
	siz[u]=1; if(!head[u]) return ;
	for(int i=head[u];i;i=e[i].nxt){
		dfs(e[i].v),siz[u]+=siz[e[i].v];
	}
	for(int i=head[u];i;i=e[i].nxt){
		ans=ans*inv[siz[e[i].v]]%mod*inv[req[e[i].v]-siz[e[i].v]]%mod;
		req[u]+=req[e[i].v];
	}
//	if(req[u]<siz[u]) puts("0"),exit(0);
	ans=ans*frc[siz[u]-1]%mod*frc[req[u]-siz[u]+1]%mod;
}
signed main(){
	File(ball);
	n=read(),frc[0]=1,ans=1; ll u;
	for(int i=2;i<=n;i++) u=read(),add(u,i);
	for(int i=1;i<=n;i++) req[i]=read(),frc[i]=frc[i-1]*i%mod;
	inv[n]=ksm(frc[n],mod-2,mod);
	for(int i=n-1;i>=0;i--) inv[i]=inv[i+1]*(i+1)%mod;
	dfs(1),printf("%lld\n",ans),exit(0);
}

C. 消失的运算符

D. 古老的序列问题

解决这种形如 \(\sum\limits_l \sum\limits_r\) 的序列问题时,有时候分治是一个比较不错的入手方向.

感觉这题比较套路,比如固定左端点、然后求右端点,离线处理然后排序做单调性等等.

基本就这些.

D_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS{
	#define int long long 
	#define lf long double
	#define pb push_back
	#define mp make_pair
	#define lb lower_bound
	#define ub upper_bound
	#define lbt(x) ((x)&(-(x)))
	#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)
	auto read=[](int w=0,bool cit=0,char ch=getchar())->int{
		for(;!isdigit(ch);ch=getchar()) cit=(ch=='-');
		for(;isdigit(ch);ch=getchar()) w=(w<<3)+(w<<1)+(ch^48);
		return cit?(-w):w;
	};
} using namespace BSS;

const int N=1e5+21,inf=1e15,mod=1e9+7;

#define ls (x<<1)
#define rs (x<<1|1)

int m,n,ops;
int mx[N],mn[N],mul[N],val[N],ans[N],org[N],f[N<<2];
struct I { 
	int l,r,id; 
	I(){}
	I(int l_,int r_,int id_) : l(l_),r(r_),id(id_) {}
};
vector<I> vec[N<<2];
struct Seg_Tree{
	struct I { int w,sum,lzy; } tr[N<<2];
	inline void getval(int x,int w){
		tr[x].sum=(tr[x].sum+tr[x].w*w%mod)%mod,tr[x].lzy=(tr[x].lzy+w)%mod;
	}
	inline void pushup(int x){
		tr[x].sum=(tr[ls].sum+tr[rs].sum)%mod;
	}
	inline void spread(int x){
		int &lzy=tr[x].lzy; if(!lzy) return ;
		getval(ls,lzy),getval(rs,lzy),lzy=0;
	}
	inline void build(int x,int l,int r,int a[]){
		tr[x].w=0,tr[x].sum=0,tr[x].lzy=0;
		if(l==r) return tr[x].w=a[l],void();
		int mid=(l+r)>>1; 
		build(ls,l,mid,a),build(rs,mid+1,r,a);
		tr[x].w=(tr[ls].w+tr[rs].w)%mod;
	};
	inline void upd(int x,int l,int r,int ql,int qr,int w){
		if(ql>qr) return ;
		if(l>=ql and r<=qr) return getval(x,w),void();
		int mid=(l+r)>>1; spread(x);
		if(ql<=mid) upd(ls,l,mid,ql,qr,w);
		if(qr>mid) upd(rs,mid+1,r,ql,qr,w);
		pushup(x);
	}
	inline int qry(int x,int l,int r,int ql,int qr){
		if(ql>qr) return 0;
		if(l>=ql and r<=qr) return tr[x].sum;
		int mid=(l+r)>>1,res=0; spread(x);
		if(ql<=mid) res+=qry(ls,l,mid,ql,qr);
		if(qr>mid) res+=qry(rs,mid+1,r,ql,qr);
		return pushup(x),res%mod;
	}
}A,B,C,D;
auto query(int l,int r,int ql,int qr)->int{
	// cout<<"query:"<<l<<' '<<r<<' '<<ql<<' '<<qr<<endl;
	// cout<<A.qry(1,l,r,ql,qr)<<' '<<B.qry(1,l,r,ql,qr)<<' '<<C.qry(1,l,r,ql,qr)<<' '<<D.qry(1,l,r,ql,qr)<<endl;
	return (A.qry(1,l,r,ql,qr)+B.qry(1,l,r,ql,qr)+C.qry(1,l,r,ql,qr)+D.qry(1,l,r,ql,qr))%mod;
};
inline void solve(int x,int l,int r){
	if(l==r){
		f[x]=val[l]*val[l]%mod;
		for(auto i : vec[x]) ans[i.id]=(ans[i.id]+f[x])%mod;
		return void();
	}
	int mid=(l+r)>>1,p1=mid,p2=mid,nowmin=inf,nowmax=0;
	mx[mid]=0,mn[mid]=inf,vec[0].clear();
	for(auto i : vec[x]) if((i.l^l or i.r^r) and i.l<=mid and i.r>mid) vec[0].pb(i);
	sort(vec[0].begin(),vec[0].end(),[](I i,I j){ return i.l>j.l; });
	for(int i=mid+1;i<=r;i++){
		mx[i]=max(mx[i-1],val[i]),mn[i]=min(mn[i-1],val[i]);
		mul[i]=mx[i]*mn[i]%mod;
	}
	A.build(1,mid+1,r,org),B.build(1,mid+1,r,mul);
	C.build(1,mid+1,r,mx),D.build(1,mid+1,r,mn);
	for(int i=mid,j=0,lmj=vec[0].size();i>=l;i--){
		nowmax=max(nowmax,val[i]),nowmin=min(nowmin,val[i]);
		while(p1<r and mx[p1+1]<nowmax) p1++;
		while(p2<r and mn[p2+1]>nowmin) p2++;
		// cout<<nowmax<<' '<<nowmin<<endl;
		A.upd(1,mid+1,r,mid+1,min(p1,p2),nowmax*nowmin%mod);
		B.upd(1,mid+1,r,max(p1,p2)+1,r,1);
		if(p1<p2) C.upd(1,mid+1,r,p1+1,p2,nowmin);
		if(p1>p2) D.upd(1,mid+1,r,p2+1,p1,nowmax);
		// cout<<vec[0][j].l<<" "<<i<<" skr\n";
		while(j<lmj and vec[0][j].l==i){
			// 	cout<<i<<' '<<lmj<<" "<<j<<' '<<vec[0][j].r<<' '<<vec[0][j].id<<' '<<query(mid+1,r,i,vec[0][j].r)<<endl;
			ans[vec[0][j].id]=(ans[vec[0][j].id]+query(mid+1,r,i,vec[0][j].r))%mod,j++;
		}
	}
	for(auto i : vec[x]){
		if(i.l==l and i.r==r) continue;
		if(i.r<=mid) vec[ls].pb(i);
		else if(i.l>mid) vec[rs].pb(i);
		else vec[ls].pb(I(i.l,mid,i.id)),vec[rs].pb(I(mid+1,i.r,i.id));
	}
	f[x]=query(mid+1,r,mid+1,r);
	// cout<<"L and R:"<<l<<" "<<r<<" "<<f[x]<<endl;
	solve(ls,l,mid),solve(rs,mid+1,r);
	f[x]=(f[x]+f[ls]+f[rs])%mod;
	// cout<<"L and R:"<<l<<' '<<r<<' '<<f[x]<<' '<<f[ls]<<" "<<f[rs]<<endl;
	for(auto i : vec[x]){
		if((i.l^l) or (i.r^r)) continue;
		ans[i.id]=(ans[i.id]+f[x])%mod;
	}
}
signed main(){
	File(sequence);
	n=read(),ops=read(); int l,r;
	for(int i=1;i<=n;i++) val[i]=read(),org[i]=1;
	for(int i=1;i<=ops;i++) l=read(),r=read(),vec[1].pb(I(l,r,i));
	solve(1,1,n); 
	for(int i=1;i<=ops;i++) printf("%lld\n",ans[i]%mod);
	exit(0);
}
posted @ 2021-10-04 06:27  AaMuXiiiiii  阅读(54)  评论(0编辑  收藏  举报