总结:人菜思维僵硬.jpg…做笔试感觉智商严重下降…以后得写点正常的AGC题之类的了…
T1
题目大意:给出长度为n的排列,要求按顺序插入排序二叉树,问经过根节点的最长路径长度。
n < = 1 e 5 n<=1e5 n<=1e5
奇怪的做法:
把数组进行排序后,把id给拿出来。
例如 A i = [ 5 , 3 , 2 , 1 , 6 , 7 , 4 ] A_i=[5,3,2,1,6,7,4] Ai=[5,3,2,1,6,7,4]
排序后得到 B i = [ 4 , 3 , 2 , 7 , 1 , 5 , 6 ] B_i=[4,3,2,7,1,5,6] Bi=[4,3,2,7,1,5,6]
B i B_i Bi为第i小的数的id。那么分治进行处理, B i B_i Bi的左边的最小数即为左儿子,右边最小即为右儿子。
这个过程用ST表处理即可。时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)。
(虽然这看上去就很不正解,如果大家有更简单的做法可以评论区告诉我Orzzz…)
C++代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
struct data_p{int id,num;}pot[100005];
int n,f[100005][25],root;
double T,lenn;
bool cmp(data_p a,data_p b){return (a.num<b.num)||(a.num==b.num&&a.id<b.id);}
int fnd(int l,int r)
{
if(l>r)return 0;
double len=1.0*log(1.0*(r-l+1))/log(2.0);int rot;
if(pot[f[l][int(len)]].id<pot[f[r-(1<<int(len))+1][int(len)]].id)rot=f[l][int(len)];
else rot=f[r-(1<<int(len))+1][int(len)];
return max(fnd(l,rot-1),fnd(rot+1,r))+1;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
pot[i].id=i;
scanf("%d",&pot[i].num);
}
sort(pot+1,pot+n+1,cmp);
T=1.0*log(1.0*n)/log(2.0);
for(int i=1;i<=n;i++){f[i][0]=i;if(pot[i].id==1)root=i;}
for(int i=1;i<=T;i++)
{
lenn=1<<i-1;
for(int j=1;j<=n-lenn*2+1;j++)
{
if(pot[f[j][i-1]].id<pot[f[int(j+lenn)][i-1]].id)f[j][i]=f[j][i-1];
else f[j][i]=f[int(j+lenn)][i-1];
}
}
printf("%d",fnd(1,root-1)+fnd(root+1,n)+1);
return 0;
}
T2
题目大意:n个男生,m个女生,选出k个人的方案数,要求至少选3个男生,2个女生。
n , m < = 1000 n,m<=1000 n,m<=1000
枚举选的男生数量,然后得到选女生的数量,直接组合数算一算即可…
C++代码:
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ll long long
#define maxn 1000005
#define inf 1e9
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
inline int read()
{
int x=0,w=1; char c=getchar();
while(c<'0'||c>'9') {if(c=='-') w=-1; c=getchar();}
while(c<='9'&&c>='0') {x=(x<<1)+(x<<3)+c-'0'; c=getchar();}
return w==1?x:-x;
}
ll fac[maxn],inv[maxn],n,k;
const ll mod=1000000007;
inline ll pw(ll a,ll b)
{
ll ans=1,base=a;
while(b)
{
if(b&1) ans=(ans*base)%mod;
base=(base*base)%mod; b>>=1;
}
return ans;
}
inline ll C(int N,int M){return (fac[N]*inv[M]%mod)*inv[N-M]%mod;}
int main()
{
fac[0]=1; inv[0]=1;
rep(i,1,(maxn-5)) fac[i]=(fac[i-1]*i)%mod;
rep(i,1,(maxn-5)) inv[i]=pw(fac[i],mod-2);
ll n,m,k,ans=0; cin>>n>>m>>k;
for(int i=max(3ll,k-m);i<=n;i++)
{
int x=k-i; if(x<2) break;
ans=(ans+(C(n,i)*C(m,x))%mod)%mod;
}
cout<<ans<<endl;
return 0;
}