Loading

noip模拟55

A. Skip

很明显的斜率式子,又发现限制很多,\(CDQ\) 直接做就行了.

当然给每个点开一个线段树维护单调栈也是可以的.

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long 
	#define ull unsigned ll
	#define lf 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=1e5+21;

ll m,n,ans;
ll dp[N],val[N],stk[N];	
struct I { ll id,w; }  p[N];
inline ll cmp1(I i,I j){ return i.w==j.w ? i.id<j.id : i.w<j.w; }
inline ll cmp2(I i,I j){ return i.id==j.id ? i.w<j.w : i.id<j.id ;} 
inline lf caly(ll x){ return (lf)(x*x+x)*1.0/2.0-(lf)dp[x]; }
inline lf calb(ll x){ return (lf)val[x]-(lf)(x*x-x)*1.0/2.0; }
inline lf slope(ll a,ll b){ return 1.0*(caly(a)-caly(b))/(lf)(a-b); }
void cdq(ll le,ll ri){
	if(le==ri) return ; 
//	cout<<"L:"<<le<<" R:"<<ri<<endl;
//	for(int i=le;i<=ri;i++) cout<<p[i].w<<' '<<p[i].id<<endl;
//	puts("");
	ll mid=(le+ri)>>1; cdq(le,mid);
	ll p1=le,p2=mid+1,l=1,r=0,id;
	sort(p+le,p+mid+1,cmp2),sort(p+mid+1,p+ri+1,cmp2);
	while(p1<=mid and p2<=ri){
		if(p[p1].id>p[p2].id){ 
			id=p[p2++].id;
			while(l<r and slope(stk[l+1],stk[l])<id) l++; 
			dp[id]=max(dp[id]*1.0,calb(id)-caly(stk[l])+id*stk[l]);
		}
		else{ 
			id=p[p1++].id;
			while(l<r and slope(stk[r],stk[r-1])>slope(id,stk[r])) r--;
			stk[++r]=id;
		}
	}
	while(p2<=ri){
		id=p[p2++].id;
		while(l<r and slope(stk[l+1],stk[l])<id) l++; 
		dp[id]=max(dp[id]*1.0,calb(id)-caly(stk[l])+id*stk[l]);
	}
	for(int i=0;i<=r;i++) stk[i]=0;
	sort(p+mid+1,p+ri+1,cmp1),cdq(mid+1,ri);
}
signed main(){
	File(skip);
	n=read(),ans=-1e15;
	for(ll i=1;i<=n;i++){
		val[i]=p[i].w=read(),p[i].id=i,dp[i]=val[i]-i*(i-1)/2;
	}
	sort(p+1,p+1+n,cmp1),cdq(1,n);
	for(int i=0;i<=n;i++){
		ans=max(ans,dp[i]-(n-i+1)*(n-i)/2);
	}
	printf("%lld\n",ans),exit(0);
}

B. String

改不出来,先咕着.

C. Permutation

数学题,找规律推式子.

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int
	#define lf double
	#define ull unsigned ll
	#define mp make_pair
	#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,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define FILE(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read(){
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

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

ll m,n,s,ans;
ll frc[N];
inline ll ksm(ll a,ll b,ll c){
	a%=c; ll res=1;
	while(b){
		if(b&1) res=(res*a)%c;
		a=(a*a)%c,b>>=1;
	}
	return res%c;
}
inline ll C(ll a,ll b){
	if(a>b) return 0;
	return frc[b]*ksm(frc[a]*frc[b-a],mod-2,mod)%mod;
}
signed main(){
	FILE(perm);
	n=read(),s=read();
	if((m=read())==1) printf("%lld\n",n-s+m-1),exit(0);
	frc[0]=1,n-=s-m,s=m;
	for(ll i=1;i<=1e6;i++) frc[i]=frc[i-1]*i%mod;
	for(ll i=2;i<=s;i++) ans=(ans+C(s-i+2,n-i))%mod;
	for(ll i=2;i<=n;i++) ans=(ans+C(s-2,n-i-1)*(i-1)%mod)%mod;
	printf("%lld\n",ans%mod),exit(0);
}

D. 小P的生成树

其实比较暴力的思想就是枚举 \(0\) ~ \(2*\pi\) 每个弧度,

然后把所有向量都投影到上面.

然而这样可以 \(A\)..

每次枚举\(0.0001\),可以过..

改成每次枚举\(0.06\),依旧可以过,复杂度变成\(O(100*mlogn)\),快的飞起..

正解的话就是把每个能使任意两个向量的相对大小都改变一下,

其实就是把所有情况都枚举了一遍.

因为最值生成树只关心相对大小.

另外,还可以维护凸包.

D_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS {
	#define ll long long int
	#define lf double
	#define ull unsigned ll
	#define mp make_pair
	#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,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define FILE(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout)
	inline ll read(){
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
} using namespace BSS;

const ll N=209;
const lf pi=acos(-1.0);

lf now,ans;
lf horn[N*N*N];

ll m,n,cnt;
ll fa[N];
struct I { ll u,v,x,y; lf w,h; } e[N];
ll find(ll x){ return x==fa[x] ? x : fa[x]=find(fa[x]); } 
inline bool comp(I i,I j){ return i.w>j.w; } 
inline void Kruscal(){
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int i=1;i<=m;i++){
		e[i].w=e[i].x*cos(now)+e[i].y*sin(now);
	}
	sort(e+1,e+1+m,comp); ll u,v,R=0,I=0;
	for(int i=1;i<=m;i++){
		u=e[i].u,v=e[i].v;
		if(find(u)==find(v)) continue ;
		R+=e[i].x,I+=e[i].y,fa[find(v)]=find(u);
	}
//	cout<<R<<' '<<I<<endl;
	ans=max(ans,sqrt(1.0*R*R+1.0*I*I));
}
signed main(){
	FILE(mst);
	n=read(),m=read(); ll u,v; lf x,y;
	for(int i=1;i<=m;i++){
		e[i].u=read(),e[i].v=read(),e[i].x=read(),e[i].y=read();
		e[i].h=1.0*e[i].y/e[i].x; // tan
	}
	for(int i=1;i<=m;i++){
		for(int j=i+1;j<=m;j++){
			x=atan(e[i].h),y=atan(e[j].h);
			if(e[i].y==e[j].y){ 
				horn[++cnt]=atan(pi/2.0),horn[++cnt]=atan(pi*3.0/2.0);
			}
			else{
				horn[++cnt]=atan(1.0*(e[i].x-e[j].x)/(e[j].y-e[i].y));
				horn[++cnt]=atan(1.0*(e[i].x-e[j].x)/(e[j].y-e[i].y))+pi;
			}
		}
	}
	sort(horn+1,horn+1+cnt),cnt=unique(horn+1,horn+1+cnt)-horn-1;
	horn[cnt+1]=horn[1];
	for(int i=1;i<=cnt;i++){
		now=(horn[i]+horn[i+1])/2.0;
		Kruscal();
		now=(horn[i]+horn[i+1])/2.0+pi;
		Kruscal();
	}
	printf("%.6lf\n",ans),exit(0);
}
posted @ 2021-09-18 06:52  AaMuXiiiiii  阅读(62)  评论(0编辑  收藏  举报