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);
}