T1 Skip

解题思路

正解给的是线段树维护单调栈,但是我不会。。 CDQ 维护斜率可做!!!

先得出一个朴素的 DP 方程:设 \(f_i\) 表示最后一场是 i 的最优解。

转移方程就是 \(f_i=\max\limits_{1\le j<i}\{f_j+s_i-\binom{i-j}{2}\}\)

然后考虑优化,转移 i 时,当 \(j>k\) 且 j 优于 k 当且仅当:

\[f_j-\dfrac{j^2+j}{2}+ij>f_k-\dfrac{k^2+k}{2}+ik
\]

设 \(g(x)=f_x-\dfrac{x^2+x}{2}\) 上述条件就变成了:

\[\dfrac{g(j)-g(k)}{j-k}>-i
\]

那么我们就可以对于横坐标为数组下标,纵坐标为 \(g(x)\) 维护一个上凸包。

然后就是 CDQ 优化斜率了,注意一个点,先处理左边的子区间,然后处理当前区间,最后处理右边的子区间就好了。

由于要在队列里面保留一个元素,因此更新答案时需要判断队首元素是否合法。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10,INF=1e18;
int n,ans=-INF,f[N],q[N];
struct Node{int id,dat;}s[N];
bool comp1(Node x,Node y){return (x.dat==y.dat)?x.id<y.id:x.dat<y.dat;}
bool comp2(Node x,Node y){return x.id<y.id;}
int g(int x){return f[x]-(x*x+x)/2;}
void CDQ(int l,int r)
{
if(l==r) return f[s[l].id]=max(f[s[l].id],s[l].dat-(s[l].id-1)*s[l].id/2),void() ;
int mid=(l+r)>>1,i=l,j=mid+1,head=1,tail=0; CDQ(l,mid);
sort(s+l,s+mid+1,comp2); sort(s+mid+1,s+r+1,comp2);
while(j<=r)
if(i<=mid&&s[i].id<s[j].id)
{
while(head<tail&&(g(s[i].id)-g(s[q[tail]].id))*(s[q[tail]].id-s[q[tail-1]].id)>=(g(s[q[tail]].id)-g(s[q[tail-1]].id))*(s[i].id-s[q[tail]].id)) tail--;
q[++tail]=i; i++;
}
else
{
while(head<tail&&(g(s[q[head+1]].id)-g(s[q[head]].id))>=-s[j].id*(s[q[head+1]].id-s[q[head]].id)) head++;
if(s[q[head]].id<s[j].id) f[s[j].id]=max(f[s[j].id],g(s[q[head]].id)+s[j].dat-(s[j].id*s[j].id-2*s[j].id*s[q[head]].id-s[j].id)/2); j++;
}
sort(s+mid+1,s+r+1,comp1); CDQ(mid+1,r);
}
signed main()
{
freopen("skip.in","r",stdin); freopen("skip.out","w",stdout);
n=read(); memset(f,128,sizeof(f));
for(int i=1;i<=n;i++) s[i].id=i,s[i].dat=read();
sort(s+1,s+n+1,comp1);CDQ(1,n);
for(int i=1;i<=n;i++) ans=max(ans,f[i]-(n-i+1)*(n-i)/2);
printf("%lld",ans); return 0;
}

T2 String

解题思路

首先,有一个结论:对于 \(k>8\) 的情况,其实只要在前面输出一些 abababa...cdcdcd...efefef 就好了。

对于 \(k\le 8\) 的情况其实就是一个记忆化搜索,因为出现次数最多是 8 ,因此我们可以压位,状态就是出现次数。

然后搜索的时候对于搜过的部分小于 rk 的直接搜下去,大于等于 rk 直接返回可以减掉的排名就好了。

搜索的时候同时记录一下每种字母出现的次数以及每种总数出现的个数。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e3+10;
int k,base,ranking,ending,cnt[N],tot[N],ch[N];
unordered_map<int,int> mp[10];
int sto(int x){if(!x)return x;return 1ll<<(4*(x-1));}
int dfs(int x,int sta,int rk,int res)
{
if(mp[res].find(sta)!=mp[res].end()&&rk>=mp[res].find(sta)->second) return mp[res].find(sta)->second;
if(sta==ending)
{
if(!rk){for(int i=1;i<x;i++) printf("%c",(char)(ch[i]+'a'));exit(0);}
return mp[res].insert(make_pair(sta,1)),1;
}
int all=0;
for(int i=base,temp;i<26;i++)
if(i!=ch[x-1])
{
ch[x]=i; cnt[i]++; tot[cnt[i]]++; temp=0;
if(tot[cnt[i]]<=k-cnt[i]+1)
temp=dfs(x+1,sta-sto(cnt[i]-1)+sto(cnt[i]),rk,cnt[i]);
all+=temp; rk-=temp; tot[cnt[i]]--; cnt[i]--;
}
return mp[res].insert(make_pair(sta,all)),all;
}
signed main()
{
freopen("string.in","r",stdin); freopen("string.out","w",stdout);
k=read(); ranking=read(); ch[0]=-1;
while(k>8)
{
for(int i=1;i<k;i++) printf("%c%c",(char)(base+'a'),(char)(base+'b'));
printf("%c",(char)(base+'a')); k-=2; base+=2;
}
for(int i=1;i<=k;i++) ending|=sto(i);
dfs(1,0,ranking-1,0); printf("-1");
return 0;
}

T3 Permutation

解题思路

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e6+10,mod=1e9+7;
int n,m,k,ans,fac[N],ifac[N];
int power(int x,int y){x%=mod;int temp=1;while(y){if(y&1)temp=temp*x%mod;x=x*x%mod;y>>=1;}return temp;}
int C(int x,int y){return fac[y]*power(fac[x]*fac[y-x],mod-2)%mod;}
signed main()
{
freopen("perm.in","r",stdin); freopen("perm.out","w",stdout);
n=read(); k=read(); m=read(); if(m==1){printf("%lld",n-k+m-1);return 0;}
fac[0]=ifac[0]=1; for(int i=1;i<=1000000;i++) fac[i]=fac[i-1]*i%mod;
ifac[n]=power(fac[n],mod-2); for(int i=n-1;i>=1;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
n-=k-m;k=m; for(int i=2;i<=k;i++) ans=(ans+C(k-i+2,n-i))%mod;
for(int i=2;i<=n;i++) ans=(ans+C(k-2,n-i-1)*(i-1)%mod)%mod;
printf("%lld",ans); return 0;
}

T4 小P的生成树

解题思路

显然我们跑最小(或者最大)生成树需要的只是一个相对的大小关系。

考虑虚数在坐标轴上的表示是向量,因此就可以推出通过任意两个向量相加得出的方向当作边界,所得到的几个区间中相对大小关系都是相同的。

因此我们直接枚举这几个边界跑最大生成树并且记录 a 和 b 的和最后答案取个最大值就好了。

当然有个 \(\mathcal{O}{m^2logm}\) 的做法,但是我太菜了不会。。。

code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=60,M=210;
const double pi=acos(-1.0);
struct Node
{
int l,r,a,b;
double len;
bool friend operator < (Node x,Node y){return x.len>y.len;}
}s[M];
int n,m,cnt,fa[N];
double ans,f[M*M*4];
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
void solve(double jiao)
{
double Sa=0,Sb=0;
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
s[i].len=cos(jiao)*s[i].a+sin(jiao)*s[i].b;
sort(s+1,s+m+1);
for(int i=1;i<=m;i++)
{
int x=s[i].l,y=s[i].r;
if(find(x)==find(y)) continue;
fa[find(x)]=find(y);
Sa+=s[i].a; Sb+=s[i].b;
}
ans=max(ans,sqrt(Sa*Sa+Sb*Sb));
}
signed main()
{
freopen("mst.in","r",stdin); freopen("mst.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=m;i++) s[i].l=read(),s[i].r=read(),s[i].a=read(),s[i].b=read();
for(int i=1;i<=m;i++)
for(int j=i+1;j<=m;j++)
{
double x=s[i].a+s[j].a,y=s[i].b+s[j].b;
f[++cnt]=acos(y/sqrt(x*x+y*y));
f[++cnt]=acos(y/sqrt(x*x+y*y))+pi;
f[++cnt]=acos(y/sqrt(x*x+y*y))+pi/2.0;
}
f[++cnt]=-pi/2.0;
for(int i=1;i<=cnt;i++) solve(f[i]);
printf("%.6lf",ans);
return 0;
}

NOIP模拟55的更多相关文章

  1. 2021.9.17考试总结[NOIP模拟55]

    有的考试表面上自称NOIP模拟,背地里却是绍兴一中NOI模拟 吓得我直接文件打错 T1 Skip 设状态$f_i$为最后一次选$i$在$i$时的最优解.有$f_i=max_{j<i}[f_j+a ...

  2. Noip模拟55 2021.9.17(打表大胜利)

    T1 skip 普通$dp$很好打: $f[i]=max(f[j]-\sum_{k=1}^{K}k+a_i)$ 就是要注意边界问题很烦人. 1 #include<bits/stdc++.h> ...

  3. CH Round #55 - Streaming #6 (NOIP模拟赛day2)

    A.九九归一 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2355%20-%20Streaming%20%236%20(NOIP模拟赛day2)/九九归一 题 ...

  4. contesthunter暑假NOIP模拟赛第一场题解

    contesthunter暑假NOIP模拟赛#1题解: 第一题:杯具大派送 水题.枚举A,B的公约数即可. #include <algorithm> #include <cmath& ...

  5. 大家AK杯 灰天飞雁NOIP模拟赛题解/数据/标程

    数据 http://files.cnblogs.com/htfy/data.zip 简要题解 桌球碰撞 纯模拟,注意一开始就在袋口和v=0的情况.v和坐标可以是小数.为保险起见最好用extended/ ...

  6. NOIP模拟题汇总(加厚版)

    \(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...

  7. NOIP模拟 1

    NOIP模拟1,到现在时间已经比较长了.. 那天是6.14,今天7.18了 //然鹅我看着最前边缺失的模拟1,还是终于忍不住把它补上,为了保持顺序2345重新发布了一遍.. #   用  户  名   ...

  8. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  9. NOIP 模拟4 T2

    本题属于二和一问题 子问题相互对称 考虑对于问题一:知a求b 那么根据b数组定义式 显然能发现问题在于如何求dis(最短路) 有很多算法可供选择 dijsktra,floyed,bfs/dfs,spf ...

  10. noip模拟29[简单的板子题](虽然我不会)

    \(noip模拟29\;solutions\) 这次考试给我最大的伤害,让我意识到了差距 这场考试可以说是非常的简单,就是简单到,看两眼,打个表就有结果了 但是呢?我考得非常的完蛋,只有30pts 据 ...

随机推荐

  1. sql 语句系列(行与列处理)[八百章之第一章]

    排序时对null进行处理 比如说: select * from EMP order by COMM 我需要对红框部分进行desc处理,也就是从大到小排列. 解析: 重点是如何让null独立出去. se ...

  2. 重新点亮linux 命令树————文件列表查看命令[二]

    前言 整理一下文件查看命令 正文 主要是pwd和ls命令 pwd 这个是一个非常常用的命令,在shell脚本中基本都有,表示的是当前目录. 这是一个非常简单,但是非常实用的命令. 通过使用pwd -- ...

  3. python中的赋值、浅拷贝、深拷贝的区别

    赋值: 可变类型:赋值前后id不会变,赋值后的数据会随源数据变化: 不可变类型:赋值前后id不会变,赋值后的数据不会随源数据变化: 浅拷贝(copy): 可变类型:copy前后id会变,可变类型中存储 ...

  4. 《Effective C#》系列之(三)——充分利用C#语言的新功能

    在<Effective C#>这本书中,利用C#语言的新功能是其中一章的内容.以下是该章节的一些核心建议,以及使用C#代码示例说明: 利用自动属性:在C# 3.0中引入了自动属性,可以大大 ...

  5. ClkLog自定义事件分析登场

     ClkLog的自定义事件分析功能在大家满满的期待下终于发布了. 这次更新我们添加了[用户关联].[事件采集].[事件分析]三大块功能点. 本次上线的自定义事件分析可以让用户根据自身业务场景创建不同维 ...

  6. 当服务器间通讯出现No route to host(Host unreachable)

    服务器间通讯出现No route to host(Host unreachable) 背景:因为某些原因,主机房服务器集体重启,其中部署的系统也需要重启,负责的系统是五台服务器,两台用来作为应用的应用 ...

  7. Oracle ORA-12725 unmatched parentheses in regular expression

    Oracle ORA-12725 unmatched parentheses in regular expression 简单来说就是正则表达式中的括号问题 这种一般就可以锁定使用正则的函数,例如 r ...

  8. linux中nginx的https证书过期替换

    linux中nginx的https证书过期替换 工作记录,不然老是忘 一般提示这个就说明过期了 首先把新的证书换上去,最好和之前的文件名字一样,这样就不用改配置文件了 路径就自己找了需要,不过一般挺好 ...

  9. 牛客网-SQL专项训练18

    ①在下列sql语句错误的是?B 解析: 在sql中若要取得NULL,则必须通过IS NULL或者IS NOT NULL进行获取,无法直接使用等号. 一个等号(=)表示把1赋值给变量啊 ==:称为等值符 ...

  10. 深入浅出eBPF|你要了解的7个核心问题

    简介: 过去一年,ARMS基于eBPF技术打造了Kubernetes监控,提供多语言无侵入的应用性能,系统性能,网络性能观测能力,验证了eBPF技术的有效性.eBPF技术和生态发展很好,未来前景广大, ...