PKUSC 模拟赛 day2 下午总结

时间:2022-12-19 19:22:22

终于考完了,下午身体状况很不好,看来要锻炼身体了,不然以后ACM没准比赛到一半我就挂掉了

下午差点AK,有一道很简单的题我看错题面了所以没有A掉

第一题显然是非常丝薄的题目

我们很容易通过DP来O(n^2)的求出深度至多为k的方案

然后我们很容易通过DP来O(n^2)的求出深度至多为k-1的方案

转移的时候分当前放左括号或者右括号讨论就可以了

两个作差就是答案了,单次询问时间复杂度O(n^2)

如果给dp加一维O(n^3)预处理,O(1)回答

当然要写高精度

成功抢到下午的first blood,请叫我手速狗,汪

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std; const int mod=10000;
int n,k,kase;
struct big_num{
int a[22],len;
void add(const big_num &A){
len=max(A.len,len)+1;
for(int i=1;i<=len;++i)a[i]=a[i]+A.a[i];
for(int i=1;i<=len;++i){
a[i+1]+=a[i]/mod;
a[i]%=mod;
}
while(len>0&&a[len]==0)len--;
}
void minus(const big_num &A){
for(int i=1;i<=len;++i){
if(a[i]<A.a[i])a[i+1]--,a[i]=a[i]+mod-A.a[i];
else a[i]=a[i]-A.a[i];
}
while(len>0&&a[len]==0)len--;
}
void print(){
printf("Case %d: ",kase);
printf("%d",a[len]);
for(int i=len-1;i>=1;--i)printf("%04d",a[i]);
printf("\n\n");
}
void clear(){len=1;memset(a,0,sizeof(a));}
}f[102][52],ans; int main(){
while(scanf("%d%d",&n,&k)==2){
if(!n&&!k)break;
f[0][0].len=1;f[0][0].a[1]=1;
n<<=1;kase++;
for(int i=1;i<=n;++i){
for(int j=0;j<=k;++j){
f[i][j].clear();
if(j>0)f[i][j].add(f[i-1][j-1]);
if(j<k)f[i][j].add(f[i-1][j+1]);
}
}
ans=f[n][0];
for(int i=1;i<=n;++i){
for(int j=0;j<=k-1;++j){
f[i][j].clear();
if(j>0)f[i][j].add(f[i-1][j-1]);
if(j<k-1)f[i][j].add(f[i-1][j+1]);
}
}
ans.minus(f[n][0]);
ans.print();
}return 0;
}

第二题保证每个点恰好属于一个环,求最长环

我能想到的有两种做法:

1、这题目显然是点双的裸题QAQ

2、用并查集建树,之后枚举非树边计算环的大小更新答案

由于上午点双的阴影还在,所以果断写了第二种做法

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std; const int maxn=5010;
int T,n,m;
int f[maxn];
int h[maxn],cnt=0;
bool check[maxn];
struct edge{
int to,next;
}G[3000010];
struct Edge{
int u,v;
}c[3000010];
int fa[maxn],dep[maxn];
int anc[maxn][20]; void read(int &num){
num=0;char ch=getchar();
while(ch<'!')ch=getchar();
while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
}
void add(int x,int y){
++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;
}
int ufs(int x){
return f[x]==x?x:f[x]=ufs(f[x]);
}
void DFS(int u,int f){
fa[u]=f;
for(int i=h[u];i;i=G[i].next){
int v=G[i].to;
if(v==f)continue;
dep[v]=dep[u]+1;
DFS(v,u);
}return;
}
void pre_LCA(){
for(int i=1;i<=n;++i){
anc[i][0]=fa[i];
for(int j=1;(1<<j)<=n;++j)anc[i][j]=-1;
}
for(int j=1;(1<<j)<=n;++j){
for(int i=1;i<=n;++i){
if(anc[i][j-1]!=-1){
int a=anc[i][j-1];
anc[i][j]=anc[a][j-1];
}
}
}return;
}
int LCA(int p,int q){
if(dep[p]<dep[q])swap(p,q);
int log;
for(log=0;(1<<log)<=dep[p];++log);--log;
for(int i=log;i>=0;--i){
if(dep[p]-(1<<i)>=dep[q])p=anc[p][i];
}
if(p==q)return p;
for(int i=log;i>=0;--i){
if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){
p=anc[p][i];q=anc[q][i];
}
}return fa[p];
} int main(){
read(T);
while(T--){
read(n);read(m);
memset(h,0,sizeof(h));cnt=0;
for(int i=1;i<=n;++i)f[i]=i,dep[i]=0;
for(int i=1;i<=m;++i)check[i]=false;
for(int i=1;i<=m;++i){
read(c[i].u);read(c[i].v);
int d1=ufs(c[i].u),d2=ufs(c[i].v);
if(d1!=d2){
f[d1]=d2;
add(c[i].u,c[i].v);
add(c[i].v,c[i].u);
check[i]=true;
}
}
for(int i=1;i<=n;++i)if(ufs(i)==i)DFS(i,-1);
pre_LCA();
int ans=0;
for(int i=1;i<=m;++i){
if(!check[i]){
int lca=LCA(c[i].u,c[i].v);
ans=max(ans,dep[c[i].u]+dep[c[i].v]-2*dep[lca]+1);
}
}printf("%d\n",ans);
}return 0;
}

第三题是原题QAQ

我背后缀数组模板的时候背的题目

曾经跟lyc说过这道题目可以用SAM做,然后是论文题

然而SAM的极限时间复杂度是O(n*sqrt(n)),感觉多笔测资有些虚

考试后发现他们都写得SAM QAQ 貌似可以卡住的样子 QAQ

后缀数组码码码,明显后缀数组很不熟练,写了30min才写完

比其他模板写的慢多了QAQ 然后除了被系统卡了rank的关键字之外1A

真是舒爽

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1000010;
int n,L,R,kase;
int s[maxn],now;
int cnt=-1;
int pos[maxn];
int wa[maxn],wb[maxn],w[maxn],wv[maxn];
int sa[maxn],height[maxn],rk[maxn];
int vis[1010],tim;
void get(int id){
char ch=getchar();
while(ch<'!')ch=getchar();
while(ch>='a'&&ch<='z'){s[++cnt]=(int)(ch)+200;pos[cnt]=id;ch=getchar();}
s[++cnt]=++now;
}
bool cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
void get_da(int n,int m){
int *x=wa,*y=wb,*t;
for(int i=0;i<m;++i)w[i]=0;
for(int i=0;i<n;++i)w[x[i]=s[i]]++;
for(int i=1;i<m;++i)w[i]+=w[i-1];
for(int i=n-1;i>=0;--i)sa[--w[x[i]]]=i;
for(int p=1,j=1;p<n;j<<=1,m=p){
p=-1;
for(int i=n-j;i<n;++i)y[++p]=i;
for(int i=0;i<n;++i)if(sa[i]>=j)y[++p]=sa[i]-j;
for(int i=0;i<n;++i)wv[i]=x[y[i]];
for(int i=0;i<m;++i)w[i]=0;
for(int i=0;i<n;++i)w[wv[i]]++;
for(int i=1;i<m;++i)w[i]+=w[i-1];
for(int i=n-1;i>=0;--i)sa[--w[wv[i]]]=y[i];
t=x;x=y;y=t;x[sa[0]]=0;p=1;
for(int i=1;i<n;++i)x[sa[i]]=cmp(t,sa[i],sa[i-1],j)?p-1:p++;
}
for(int i=0;i<n;++i)rk[sa[i]]=i;
int k=0;
for(int i=0;i<n;++i){
if(rk[i]==0){height[rk[i]]=0;continue;}
if(k)--k;
int j=sa[rk[i]-1];
while(s[j+k]==s[i+k])k++;
height[rk[i]]=k;
}return;
}
bool check(int blo){
int tot=0;
for(int i=n;i<=cnt;++i){
if(height[i]<blo){
tim++;tot=1;
vis[pos[sa[i]]]=tim;
}
else{
if(vis[pos[sa[i]]]!=tim)vis[pos[sa[i]]]=tim,tot++;
if(tot>n/2)return true;
}
}return false;
}
void print(){
if(L==0){printf("?\n");return;}
int tot=0;
for(int i=n;i<=cnt;++i){
if(height[i]<L){
tim++;
if(tot>n/2){
for(int j=sa[i-1];j<=sa[i-1]+L-1;++j)putchar(s[j]-200);
printf("\n");
}tot=1;vis[pos[sa[i]]]=tim;
}else{
if(vis[pos[sa[i]]]!=tim)vis[pos[sa[i]]]=tim,tot++;
}
}
if(tot>n/2){
for(int j=sa[cnt];j<=sa[cnt]+L-1;++j)putchar(s[j]-200);
printf("\n");
}return;
}
int main(){
while(scanf("%d",&n)==1){
if(n==0)break;
if(kase)printf("\n");
kase++;cnt=-1;now=0;
for(int i=1;i<=n;++i)get(i);
get_da(cnt+1,1000);
memset(vis,0,sizeof(vis));tim=1;
L=0,R=cnt;
while(L<R){
int mid=L+(R-L+1)/2;
if(check(mid))L=mid;
else R=mid-1;
}
print();
}return 0;
}

第四题好难读的题面,然后读懂了就很容易发现是个斗地主的弱化版

随便写写就好啦

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std; int T,kase;
char s[22][22];
char t[22][22];
int vis[4][12];
int tmp[1010]; bool DFS(int num){
if(num==12){
for(int i=1;i<=3;++i){
for(int j=1;j<=9;++j){
if(vis[i][j]==2)return true;
}
}return false;
}
for(int i=1;i<=3;++i){
for(int j=1;j<=9;++j){
if(vis[i][j]){
if(vis[i][j]>=3){
vis[i][j]-=3;
if(DFS(num+3))return true;
vis[i][j]+=3;
}
if(vis[i][j+1]&&vis[i][j+2]){
vis[i][j]--;
vis[i][j+1]--;
vis[i][j+2]--;
if(DFS(num+3))return true;
vis[i][j]++;
vis[i][j+1]++;
vis[i][j+2]++;
}
}
}
}return false;
} bool check(){
memset(vis,0,sizeof(vis));
for(int i=1;i<=14;++i)vis[tmp[s[i][2]]][s[i][1]-'0']++;
for(int i=1;i<=3;++i){
for(int j=1;j<=9;++j){
if(vis[i][j]>4)return false;
}
}
if(DFS(0))return true;
return false;
} int main(){
scanf("%d",&T);
tmp['s']=1;tmp['b']=2;tmp['c']=3;
while(T--){
kase++;int cnt=0;
for(int i=1;i<=13;++i)scanf("%s",s[i]+1);
printf("Case %d:",kase);
for(int i=1;i<=3;++i){
if(i==1)s[14][2]='s';
else if(i==2)s[14][2]='b';
else s[14][2]='c';
for(int j=1;j<=9;++j){
s[14][1]=j+'0';
if(check()){
printf(" ");cnt++;
putchar(s[14][1]);
putchar(s[14][2]);
}
}
}
if(!cnt)printf(" None");
printf("\n");
}return 0;
}

第五题考试的时候一直看错题,然后就没有A掉

后来听lyc说了题意之后发现是个背包的丝薄题

看对题之后随便写写就A啦

正确性的证明是因为答案是个二次函数QAQ

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cstdlib>
using namespace std; typedef long long LL;
const int maxn=110;
const LL oo=1LL<<60;
int n,L;
LL sa,sc;
int c[maxn],a[maxn];
LL f[maxn][maxn][502]; int main(){
scanf("%d%d",&n,&L);
for(int i=1;i<=n;++i)scanf("%d",&a[i]),sa+=a[i];
for(int i=1;i<=n;++i)scanf("%d",&c[i]),sc+=c[i];
for(int i=0;i<=n;++i)for(int j=0;j<=n;++j)for(int k=0;k<=sa;++k)f[i][j][k]=oo;
f[0][0][0]=0;
for(int i=1;i<=n;++i){
for(int j=0;j<=n;++j){
for(int k=0;k<=sa;++k){
f[i][j][k]=f[i-1][j][k];
if(k>=a[i]&&j>=1)f[i][j][k]=min(f[i][j][k],f[i-1][j-1][k-a[i]]+c[i]);
}
}
}
double ans=1e13;
for(int i=1;i<=n;++i){
if(i==L||n-i==L){
for(int k=1;k<=sa-1;++k){
if(f[n][i][k]!=oo){
double now=(double)(f[n][i][k])/(double(k))*(double)(sc-f[n][i][k])/(double)(sa-k);
ans=min(ans,now);
}
}
}
}printf("%.3lf\n",ans);
return 0;
}

第六题正解是维护凸包,每次二分斜率求最优值做DP就可以了

然后考试的时候没有太多时间,很容易发现答案是fi+ci*abs(xi-xj)的形式

两边项次数都是一次

下面不加证明的给出以下结论:

1、当两边项都是二次的时候,使用KD_Tree并定期重构保证不退化时间复杂度较优

2、当两边项一个一次一个二次的时候,使用平衡树以二次项为键值维护并做KD_Tree的查询较优

3、当两边项均为一次时,使用线段树同时维护两个信息并做KD_Tree的查询较优

然后本题显然两个一次直接线段树+KD_Tree就可以啦

其实这个题目是式子是省选模拟某套题目的第一题的式子?

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std; typedef long long LL;
const int maxn=100010;
const int oo=0x7fffffff;
int n;
int x[maxn],c[maxn],t[maxn];
int l[maxn<<2],r[maxn<<2];
LL mxd[maxn<<2],mxc[maxn<<2];
LL dp[maxn],now,k; void UPD(int o,int L,int R,int p,LL d,LL c,int x){
if(L==R){mxd[o]=d;mxc[o]=c;l[o]=x;r[o]=x;return;}
int mid=(L+R)>>1;
if(p<=mid)UPD(o<<1,L,mid,p,d,c,x);
else UPD(o<<1|1,mid+1,R,p,d,c,x);
mxd[o]=max(mxd[o<<1],mxd[o<<1|1]);
mxc[o]=max(mxc[o<<1],mxc[o<<1|1]);
l[o]=min(l[o<<1],l[o<<1|1]);
r[o]=max(r[o<<1],r[o<<1|1]);
}
void ask(int o,int L,int R,int x,int y){
if(L>=x&&R<=y){
if(L==R)now=max(now,mxd[o]+mxc[o]*abs(l[o]-k));
else{
LL d1=mxd[o<<1]+mxc[o<<1]*max(abs(l[o<<1]-k),abs(r[o<<1]-k));
LL d2=mxd[o<<1|1]+mxc[o<<1|1]*max(abs(r[o<<1|1]-k),abs(l[o<<1|1]-k));
int mid=(L+R)>>1;
if(d1>d2){
if(d1>now)ask(o<<1,L,mid,x,y);
if(d2>now)ask(o<<1|1,mid+1,R,x,y);
}else{
if(d2>now)ask(o<<1|1,mid+1,R,x,y);
if(d1>now)ask(o<<1,L,mid,x,y);
}
}return;
}
int mid=(L+R)>>1;
if(y<=mid)ask(o<<1,L,mid,x,y);
else if(x>mid)ask(o<<1|1,mid+1,R,x,y);
else ask(o<<1,L,mid,x,y),ask(o<<1|1,mid+1,R,x,y);
} int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%d%d%d",&x[i],&c[i],&t[i]);
for(int i=1;i<=(n<<2);++i)l[i]=oo,r[i]=-oo;
UPD(1,1,n,1,0,c[1],x[1]);
for(int i=2;i<=n;++i){
now=0;k=x[i];
ask(1,1,n,1,i-1);
dp[i]=now+t[i];
UPD(1,1,n,i,dp[i],c[i],x[i]);
}printf("%lld\n",dp[n]);
return 0;
}

今天下午发挥的较为不错

直接说缺点吧:

1、第三题的后缀数组模板不熟练,拖了一些时间

2、身体素质不太好,在四点半以后就开始狂吐不止,没有什么精力去仔细看第五题,导致第五题并没有A掉

PKUSC 模拟赛 day2 下午总结的更多相关文章

  1. PKUSC 模拟赛 day1 下午总结

    下午到了机房之后又困又饿,还要被强行摁着看英文题,简直差评 第一题是NOIP模拟赛的原题,随便模拟就好啦 本人模拟功力太渣不小心打错了个变量,居然调了40多分钟QAQ #include<cstd ...

  2. PKUSC 模拟赛 day2 上午总结

    今天上午考得不是很好,主要还是自己太弱QAQ 开场第一题给的图和题意不符,搞了半天才知道原来是走日字形的 然后BFS即可 #include<cstdio> #include<cstr ...

  3. CH Round &num;58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  4. CH Round &num;49 - Streaming &num;4 &lpar;NOIP模拟赛Day2&rpar;

    A.二叉树的的根 题目:http://www.contesthunter.org/contest/CH%20Round%20%2349%20-%20Streaming%20%234%20(NOIP 模 ...

  5. CH Round &num;55 - Streaming &num;6 &lpar;NOIP模拟赛day2&rpar;

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

  6. PKUSC 模拟赛 题解&lowbar;UPD

    之前挖了两个大坑 一个是day1下午的第二题 另一个是day2上午的第五题 先说day1下午的第二题吧 我们显然不能O(n^2)的dp,所以我们只能算贡献 首先对于任意一个边界点而言,他对答案的贡献路 ...

  7. CH Round &num;55 - Streaming &num;6 &lpar;NOIP模拟赛day2&rpar;解题报告

    T1九九归一 描述 萌蛋在练习模n意义下的乘法时发现,总有一些数,在自乘若干次以后,会变成1.例如n=7,那么5×5 mod 7=4,4×5 mod 7=6,6×5 mod 7=2,2×5 mod 7 ...

  8. 【洛谷】NOIP提高组模拟赛Day2【动态开节点&sol;树状数组】【双头链表模拟】

    U41571 Agent2 题目背景 炎炎夏日还没有过去,Agent们没有一个想出去外面搞事情的.每当ENLIGHTENED总部组织活动时,人人都说有空,结果到了活动日,却一个接着一个咕咕咕了.只有不 ...

  9. l洛谷 NOIP提高组模拟赛 Day2

    传送门 ## T1 区间修改+单点查询.差分树状数组. #include<iostream> #include<cstdio> #include<cstring> ...

随机推荐

  1. java解析命令行参数&lpar;common-cli&rpar;练习

    package foo; import org.apache.commons.cli.BasicParser; import org.apache.commons.cli.CommandLine; i ...

  2. Redis内存存储结构分析

    1 Redis 内存存储结构 本文是基于 Redis-v2.2.4 版本进行分析. 1.1 Redis 内存存储总体结构 Redis 是支持多key-value数据库(表)的,并用 RedisDb 来 ...

  3. DOM基础总结

    一.简介 1.什么是DOM 文档对象模型(Document Object Model,DOM)是一种用于HTML和XML文档的编程接口.它给文档提供了一种结构化的表示方法,可以改变文档的内容和呈现方式 ...

  4. ROW&lowbar;NUMBER 使用

    WITH t_pageAS( SELECT ROW_NUMBER() OVER ( ORDER BY table_name ) AS row_index,column_name FROM table_ ...

  5. asp&period;net 如何改变GridView搜索出来关键字的颜色?就像百度似的,我获得的是一个集合,改变集合中关键字的集合

    输入“产量”查询,将“产量”拆分,产.量 string strColNameCnDt = string.Empty;            for (int j = 0; j < dtTemp. ...

  6. 关于Get和Post的学习笔记&lpar;五&rpar;

    一 .Get和Post的优缺点 1. Get> 优点: 编写起来比较简单,只要在地址后面拼接数据即可. > 缺点: 提交的数据有长度限制.安全性比较差 2.Post > 优点: 提交 ...

  7. bigdata&lowbar;spark&lowbar;源码修改&lowbar;本地环境搭建&lowbar;eclise

    Eclipse 下开发调试环境的配置该小节中使用的各项工具分别为:mac (Windows 7)+Eclipse Java EE 4.4.2+Scala 2.10.4+Sbt 0.13.8+Maven ...

  8. &&num;39&semi;JetEntityFrameworkProvider&&num;39&semi; could not be loaded 解决办法

    原因:JetEntityFrameworkProvider引用的EntityFramework与你使用的版本不一致,造成程序加载这个DLL失败. 解决办法: 使用Reflect软件JetEntityF ...

  9. PHP抽象类

    <?php /* * abstract * 抽象类: * 1.至少有一个抽象方法(没有具体实现的方法) * 2.不能被实例化,可以被继承 * 3.抽象类可以有子抽象类 * 相对于接口: * 1. ...

  10. spark提示Caused by&colon; java&period;lang&period;ClassCastException&colon; scala&period;collection&period;mutable&period;WrappedArray&dollar;ofRef cannot be cast to &lbrack;Lscala&period;collection&period;immutable&period;Map&semi;

    spark提示Caused by: java.lang.ClassCastException: scala.collection.mutable.WrappedArray$ofRef cannot b ...