【题目地址】点击打开链接
【分析们】
【T-1】
树状数组+Trie树
【T-2】
首先显然这是个堆,这个堆以位置为关键字,且形状固定。
我们要做的就是将数字1~N填入堆中,并且令这些数字也满足堆性质。
考虑我们有一个以x为根的堆,有i个数字可以填。
我们用M[i]表示以i为根的堆的结点个数,可以逆序O(N)求得。
用f[i]表示有i个数的方案数。
我们得到一个方程:
f[i]=C(i-1,m)*f[m]*f[i-1-m] (m=M[x<<1])
即选择m个分给左儿子,i-1-m个分给右儿子。
具体实现的时候可以用记忆化搜索,注意边界。
复杂度是O(N+log2N)吧
【T-3】
显然最后的形状是一个下凸的单峰函数。
我们直接用三分法求得。
注意将误差阀值设小一点,至少要1e-9才能过。
【代码们】
【T-1】
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
#include <ctime>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define INF (~0U>>1)
#define p_b push_back
#define sf scanf
#define pf printf
#define lowbit(x) ((x)&((~(x))+1))
#define MAXN 100010
#define val(x) ((x)+N)
struct TrieNode{
#define node TrieNode
node* ch[2];
int sz;
node(){
ch[0]=ch[1]=NULL;
sz=0;
}
}*null=new node(),*root[MAXN],pool[MAXN*400],*New=pool;
int N,M;
int A[MAXN];
vector <node*> Plus;
vector <node*> Sub;
node* Get(){
New->ch[0]=New->ch[1]=null;
New->sz=0;
return New++;
}
void Read(int& x,bool mark=0){
char tt=getchar();
for(;tt<'0'||'9'<tt;tt=getchar()) if(tt=='-') mark=1;
for(x=0;'0'<=tt&&tt<='9';x=(x<<1)+(x<<3)+tt-'0',tt=getchar());
x=mark?-x:x;
}
void Insert(node* p,int key){
rrep(i,21,0){
p->sz++;
int t=(key>>i)&1;
if(p->ch[t]==null) p->ch[t]=Get();
p=p->ch[t];
}
p->sz++;
}
void Delete(node* p,int key){
rrep(i,21,0){
p->sz--;
int t=(key>>i)&1;
p=p->ch[t];
}
p->sz--;
}
void Init(){
Read(N);
Read(M);
rep(i,1,N){
Read(A[i]);
for(int j=i;j<=N;j+=lowbit(j)){
if(!root[j]) root[j]=Get();
Insert(root[j],val(A[i]));
}
}
}
int Select(int k){
int rt=0;
int n=Plus.size();
int m=Sub.size();
rrep(i,21,0){
int tmp=0,dir=1;
rep(j,0,n-1) tmp+=Plus[j]->ch[1]->sz;
rep(j,0,m-1) tmp-=Sub[j]->ch[1]->sz;
if(k>tmp){
k-=tmp;
dir=0;
}
else rt+=(1<<i);
rep(j,0,n-1) Plus[j]=Plus[j]->ch[dir];
rep(j,0,m-1) Sub[j]=Sub[j]->ch[dir];
}
return rt-N;
}
void Solve(){
int K,a,b,k,p,s;
while(M--){
Read(K);
if(K==1){
Read(a);
Read(b);
Read(k);
for(int j=b;j;j-=lowbit(j))
Plus.p_b(root[j]);
for(int j=a-1;j;j-=lowbit(j))
Sub.p_b(root[j]);
pf("%d\n",Select(k));
Plus.clear();
Sub.clear();
}
else{
Read(p);
Read(s);
for(int j=p;j<=N;j+=lowbit(j)){
Delete(root[j],val(A[p]));
Insert(root[j],val(s));
}
A[p]=s;
}
}
}
int main(){
null->ch[0]=null;
null->ch[1]=null;
Init();
Solve();
return 0;
}
【T-2】
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i,a,b) for(register int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(register int i=(b);i>=(a);--i)
#define INF (~0U>>1)
#define p_b push_back
#define ll long long
#define sf scanf
#define pf printf
#define MAXN 1000010
int N;
ll MODER;
ll f[MAXN];
ll V[MAXN];
int M[MAXN];
void Init(){
cin>>N>>MODER;
V[0]=1;
rep(i,1,N){
V[i]=V[i-1]*i%MODER;
}
}
ll Inv(ll a){
ll b=MODER-2;
ll rt=1;
while(b){
if(b&1) rt=(rt*a)%MODER;
b>>=1;
a=(a*a)%MODER;
}
return rt;
}
ll C(int i,int j){
ll fz=V[i];
ll fm=V[j]*V[i-j]%MODER;
return fz*Inv(fm)%MODER;
}
ll Dfs(ll x,ll i){
if(x>N||i==0) return 1;
if(f[i]) return f[i];
int m=((x<<1)<=N)?M[x<<1]:0;
return f[i]=(C(i-1,m)*Dfs(x*2,m))%MODER*Dfs(x*2+1,i-1-m)%MODER;
}
void Solve(){
rrep(i,N,1){
if(i*2<=N) M[i]+=M[i*2];
if(i*2+1<=N) M[i]+=M[i*2+1];
M[i]++;
}
Dfs(1,N);
cout<<f[N]<<endl;
}
int main(){
Init();
Solve();
return 0;
}
【T-3】
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define rrep(i,b,a) for(int i=(b);i>=(a);--i)
#define INF (~0U>>2)
#define p_b push_back
#define sf scanf
#define pf printf
#define MAXN 10010
#define eps (1e-10)
int N;
double A[MAXN];
double B[MAXN];
double C[MAXN];
void Init(){
sf("%d",&N);
rep(i,1,N){
sf("%lf%lf%lf",&A[i],&B[i],&C[i]);
}
}
double F(double x){
double rt=A[1]*x*x+B[1]*x+C[1];
rep(i,2,N){
rt=max(rt,A[i]*x*x+B[i]*x+C[i]);
}
return rt;
}
void Solve(){
double l=0.0,r=1000.0;
while(fabs(l-r)>eps){
double m1=l+(r-l)/3;
double m2=r-(r-l)/3;
if(F(m1)<F(m2)){
r=m2;
}
else{
l=m1;
}
}
pf("%.4lf\n",F(l));
}
int main(){
int T;
sf("%d",&T);
while(T--){
Init();
Solve();
}
return 0;
}