十二省联考题解 - JLOI2019 题解

十二省联考题解 - JLOI2019 题解

两个T3的难度较大

平均代码量远大于去年省选

套路题考查居多

A

难度等级 1

$n^2$暴力可以拿到$60$分的优秀成绩

然后可以想到把区间异或转化为前缀两点异或

可以想到使用二分答案的方法+可持久化Trie解决,但是时间复杂度为$n\log^2 (4294967295) $

这是唯一一通过不了的$poly(\log)$做法,常数不够优秀的话会得到$60$分,卡一卡说不定可以$80$,理论上能卡到$100$

然后可以通过将二分放在可持久化Trie上,将复杂度降为$ n \log(4294967295)$,可以通过此题

然后还有一种维护类似于超级钢琴的做法,我并不了解

对于我改题的时候,写的是一个可持久化Trie+堆的做法,我们维护一个大根堆,将以$i$为结尾的区间中最大的推入堆

然后每次找到堆顶,查找对应右端点下一个比这个小一点的区间是多大,然后再推入堆即可

复杂度很显然,为:$(n+k)\log (4294967295)$

// luogu-judger-enable-o2
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define N 500005
#define ll long long
int n,K,now[N];unsigned a[N];long long ans;
struct Trie
{int ch[N*33][2],siz[N*33],cnt,rot[N];inline void copy(int x,int y){siz[x]=siz[y];ch[x][0]=ch[y][0];ch[x][1]=ch[y][1];}inline void insert(unsigned x,int id){int rt=++cnt,lst=rot[id-1],t;rot[id]=rt;copy(rt,lst);for(int i=31;~i;i--){t=(x>>i)&1;ch[rt][t]=++cnt;rt=ch[rt][t];lst=ch[lst][t];copy(rt,lst);siz[rt]++;}}inline int query(unsigned x,int id,int K){int rt=rot[id],t;unsigned ret=0;for(int i=31;~i;i--){if(!rt)return ret;t=(x>>i)&1;if(K>siz[ch[rt][!t]])K-=siz[ch[rt][!t]],rt=ch[rt][t];else rt=ch[rt][!t],ret|=1u<<i;}return ret;}
}tr;
priority_queue<pair<unsigned ,int > >q;
int main()
{// freopen("xor.in","r",stdin);// freopen("xor.out","w",stdout);scanf("%d%d",&n,&K);for(int i=1;i<=n;i++)scanf("%u",&a[i]),a[i]^=a[i-1],tr.insert(a[i-1],i);for(int i=1;i<=n;i++)q.push(make_pair(tr.query(a[i],i,++now[i]),i));int t;while(K--)ans+=q.top().first,t=q.top().second,q.pop(),q.push(make_pair(tr.query(a[t],t,++now[t]),t));printf("%lld\n",ans);
}

长度较短,是一个相对简单的可持久化数据结构套路

B

难度等级 3

可以转化为一个经典的字符串问题,可以容易的想到,使用字符串hash拿到$40$分的成绩

然后可以想到使用Sa,找到满足某个位置之后的字符串是这个B串的rank区间,然后使用线段树优化建图来完成,能拿到$80$分的优秀成绩,然后我就不太会了,并且代码量较高,并不能在很短的时间内完成

同时,可以想到使用Sam解决,在后缀树上主席树合并优化建图,然后再倍增定位节点同样可以拿到$80$分的优秀成绩,但是同样,代码复杂度较高

在此基础上,我们发现,线段树合并这步没有意义,直接在后缀树上拆点连边,后缀树优化建图,就可以拿到$80$分的优秀成绩

然后在此基础上,将每个节点的长度和编号按照长度从小到大,先b后a的顺序排序,然后前缀优化建图,即可拿到$100$分的优秀成绩

代码复杂度相对不高,整体考查了选手对于字符串经典模型的转化,前缀优化建图,后缀树的基本应用等知识,对字符串方面薄弱的选手是一个沉重的打击

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define ll long long
int n,na,nb,tot,cnt_SAM,oth,p[400005];char s[200005];
namespace Graph
{const int N = 1000005;struct node{int to,next;}e[N<<2];int head[N],cnt,in[N],q[N],a[N];ll f[N];void add(int x,int y){e[cnt]=(node){y,head[x]};head[x]=cnt++;in[y]++;}void init(){cnt=0;memset(head,-1,sizeof(int)*(tot+3));memset(in,0,sizeof(int)*(tot+3));memset(a,0,sizeof(int)*(tot+3));}ll tsort(){int l=0,r=0;for(int i=1;i<=tot;i++)if(!in[i])q[r++]=i;while(l<r){int x=q[l++];for(int i=head[x];i!=-1;i=e[i].next){int to1=e[i].to;if(!(--in[to1]))q[r++]=to1;}}if(r!=tot)return -1;ll ans=0;for(int j=r-1;~j;j--){int x=q[j];f[x]=a[x];for(int i=head[x];i!=-1;i=e[i].next)f[x]=max(f[x],f[e[i].to]+a[x]);ans=max(ans,f[x]);}return ans;}
}
inline bool cmp(const pair<int ,int > &a,const pair<int ,int >&b){return a.first==b.first?a.second>b.second:a.first<b.first;}
// SAM
namespace Sam
{const int N = 400005;int trs[N][26],len[N],fa[N],pos[N],lst,cnt;vector<pair<int ,int > >s[N];inline void init(){lst=cnt=1;memset(trs[1],0,sizeof(trs[1]));fa[1]=len[1]=0;}inline int new_node(){cnt++;fa[cnt]=len[cnt]=0;memset(trs[cnt],0,sizeof(trs[cnt]));s[cnt].clear();return cnt;}inline void insert(int x,int id){int np=new_node(),nq,p=lst,q;len[np]=len[p]+1;pos[id]=np;lst=np;for(;p&&!trs[p][x];p=fa[p])trs[p][x]=np;if(!p)fa[np]=1;else if(len[q=trs[p][x]]==len[p]+1)fa[np]=q;else{len[nq=new_node()]=len[p]+1;fa[nq]=fa[q];fa[q]=fa[np]=nq;memcpy(trs[nq],trs[q],sizeof(trs[nq]));for(;p&&trs[p][x]==q;p=fa[p])trs[p][x]=nq;}}struct node{int to,next;}e[N];int head[N],edge_cnt;inline void add(int x,int y){e[edge_cnt]=(node){y,head[x]};head[x]=edge_cnt++;}int f[N][19];void dfs(int x,int from){f[x][0]=from;for(int i=1;i<19;i++)f[x][i]=f[f[x][i-1]][i-1];for(int i=head[x];i!=-1;i=e[i].next)dfs(e[i].to,x);}inline void build(){cnt_SAM=cnt;memset(head,-1,sizeof(int)*(cnt+3));edge_cnt=0;for(int i=2;i<=cnt;i++)add(fa[i],i);dfs(1,0);}inline void query(int l,int p,int id){int x=pos[p];for(int i=18;~i;i--)if(len[f[x][i]]>=l)x=f[x][i];s[x].push_back(make_pair(l,id));}inline void build_Graph(){oth=0;for(int i=2;i<=cnt;i++){sort(s[i].begin(),s[i].end(),cmp);int lim=s[i].size(),lst=i;for(int j=0;j<lim;j++){int x=s[i][j].second+cnt;p[s[i][j].second]=x;if(j==0)Graph::add(i,x);else Graph::add(s[i][j-1].second+cnt,x);lst=x;if(s[i][j].second<=na){int u=na+nb+cnt+(++oth);p[s[i][j].second]=u;Graph::add(x,u);Graph::a[u]=s[i][j].first;}}for(int j=head[i];j!=-1;j=e[j].next)Graph::add(lst,e[j].to);}}
}
int T,Case;
void solve()
{scanf("%s",s+1);n=strlen(s+1);Sam::init();for(int i=n;i;i--)Sam::insert(s[i]-'a',i);Sam::build();scanf("%d",&na);for(int i=1,l,r;i<=na;i++)scanf("%d%d",&l,&r),Sam::query(r-l+1,l,i);scanf("%d",&nb);for(int i=1,l,r;i<=nb;i++)scanf("%d%d",&l,&r),Sam::query(r-l+1,l,i+na);tot=(cnt_SAM)+(na<<1)+nb;Graph::init();Sam::build_Graph();int m;scanf("%d",&m);for(int x,y;m--;Graph::add(p[x],p[y+na]))scanf("%d%d",&x,&y);printf("%lld\n",Graph::tsort());
}
int main(){scanf("%d",&T);while(T--)Case++,solve();}

可以显然的发现,我就是那个被打击的

C

难度等级 5

这个题不太能做吧?

1_998244353直接费马小定理+快速幂就可以了

1?暴力找一个模数即可,模数为$1145141$

1?+通过找到输入数据中,输入最接近的两个数,找到对应答案里的位置,然后通过观察输出数据找到模数的大致区间,然后验证即可,模数为$5211600617818708273$

1wa_998244353,观察可以发现,这个是在乘法的过程中爆$int$了,然后第一个可以直接暴力每次乘以$19$,第二个的话,一种是可以分块打表,也可以通过找循环节搞定

2p的话,就是如果是质数,该位为$p$否则为$.$,然后8是直接线筛,9是线筛+根号求,10是$Miller-Rabin$

2u的话,就是莫比乌斯函数,前两个类似上面的前两个,最后一个打表+线筛即可

2g的话,就是原根,我不会

没写

D

难度等级 4

可以说是一个非常好的高维DP问题,数据范围具有迷惑性,让人觉得暴力能过,然后本人尝试卡常,然后失败了,最后只拿到了$50$分

我们先给出一个DP方程:$f[i][j][k][0/1]$表示前$i$个学校,蓝阵营有$j$个人,鸭派系有$k$个人的方案数,然后每次直接转移即可,特判不多,属于可以接受的范围

然后我们发现$k$比较小,所以我们考虑提出一个复杂度阈值有关$k$的做法

那么我们先从$k=0$入手

对于$k=0$的情况,我们发现,不论这个城市选择哪一个阵营,如何选择,和学校选择哪个派系没有任何关系

因为对于每个阵营,都有两个派系可以选,并且因为$k=0$所以具体选哪个阵营没啥意义

所以答案即为$选择派系的分组数\times 选择阵营的分组数$,这两个东西分别DP一下即可

然后我们考虑$k \neq 0$的情况,可以发现,一定最多只有$k$个城市和$k$个学校不会被访问

这样我们发现可以单独对这$k$个城市DP,然后剩下的的东西做一遍$k=0$的情况即可

但是我们发现,这样如果这$k$个城市的学校数=n的话,那复杂度就依然为$nm^2$就没有发生任何优化

那么我们考虑将这个问题和$k=0$结合起来

我们发现,对于这样的对于存在约束的学校,只需要正常DP一下,然后对于没有约束的学校,你只需钦定它的阵营,并不需要钦定它的派系,派系只需要最后搞一下就可以了

然后这样的话,就可以做到:$O(km^2 + n\times m)$解决了

可能会被卡常,然后稍微优化一下复杂度上届即可

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
using namespace std;
#define N 2505
#define ll long long
#define mod 998244353
int f[N][305],g[N][305],f1[N],f0[N];
int n,c,k,C0,C1,D0,D1,M,S,bel[N],sz[N],hat[N],ht[N],s[N];
void get_f0()
{f0[0]=1;for(int i=1;i<=n;i++)if(hat[i]==-1)for(int j=M;j>=sz[i];j--)f0[j]=(f0[j]+f0[j-sz[i]])%mod;for(int j=1;j<=M;j++)(f0[j]+=f0[j-1])%=mod;
}
void get_f1()
{f1[0]=1;for(int i=1;i<=c;i++)if(s[i]&&ht[i]==-1)for(int j=M;j>=s[i];j--)f1[j]=(f1[j]+f1[j-s[i]])%mod;for(int j=1;j<=M;j++)(f1[j]+=f1[j-1])%=mod;
}
inline int get(int v0,int v1)
{int l0=max(C0-v0,0),r0=min(C1-v0,M),l1=max(D0-v1,0),r1=min(D1-v1,M);if(l0>r0||l1>r1)return 0;return (ll)(f1[r0]-(l0?f1[l0-1]:0))*(f0[r1]-(l1?f0[l1-1]:0))%mod;
}
void solve()
{memset(f,0,sizeof(f));memset(g,0,sizeof(g));memset(hat,-1,sizeof(hat));S=0;memset(ht,-1,sizeof(ht));memset(f1,0,sizeof(f1));memset(f0,0,sizeof(f0));memset(s,0,sizeof(s));scanf("%d%d%d%d%d%d",&n,&c,&C0,&C1,&D0,&D1);M=max(max(C0,C1),max(D0,D1));for(int i=1;i<=n;i++)scanf("%d%d",&bel[i],&sz[i]),s[bel[i]]+=sz[i],S+=sz[i];scanf("%d",&k);for(int i=1,x,y;i<=k;i++)scanf("%d%d",&x,&y),ht[bel[x]]=hat[x]=y;get_f0();get_f1();C1=max(S-C1,0),D1=max(S-D1,0);swap(C0,C1);swap(D0,D1);if(C0>C1||D0>D1)return puts("0"),void();g[0][0]=1;int S0=0,S1=0;for(int i=1;i<=c;i++)if(ht[i]!=-1){for(int j=S0;~j;j--)for(int k=S1;~k;k--)f[j][k]=g[j][k];for(int j=1;j<=n;j++)if(bel[j]==i&&hat[j]!=-1){S1+=sz[j];if(hat[j]==1)for(int k=S0;~k;k--){for(int l=S1;l>=sz[j];l--)g[k][l]=g[k][l-sz[j]];for(int l=0;l<sz[j];l++)g[k][l]=0;}else if(hat[j]!=0)for(int k=S0;~k;k--)for(int l=S1;l>=sz[j];l--)g[k][l]=(g[k][l]+g[k][l-sz[j]])%mod;if(hat[j]==3)for(int k=S0;~k;k--){for(int l=S1;l>=sz[j];l--)f[k][l]=f[k][l-sz[j]];for(int l=0;l<sz[j];l++)f[k][l]=0;}else if(hat[j]!=2)for(int k=S0;~k;k--)for(int l=S1;l>=sz[j];l--)f[k][l]=(f[k][l]+f[k][l-sz[j]])%mod;}S0+=s[i];S0=min(S0,M);for(int j=S0;~j;j--)for(int k=S1;~k;k--)g[j][k]=((j>=s[i]?g[j-s[i]][k]:0)+f[j][k])%mod;}int ans=0;for(int i=0;i<=S0;i++)for(int j=0;j<=S1;j++)ans=(ans+(ll)g[i][j]*get(i,j))%mod;printf("%d\n",(ans+mod)%mod);
}
int main(){int T;scanf("%d",&T);while(T--)solve();}

E

难度评级 2

一道不失幽默的树上贪心数据结构问题

其实看一看就能发现,对每个子树,按照从大到小排序后,按位置合并即可

这样就能拿到$60$分的优秀成绩了

然后正解就是上述算法优化一下即可

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <iostream>
#include <bitset>
#include <set>
using namespace std;
#define N 200005
#define ll long long
multiset<int ,greater<int > >s[N];
vector<int >v;
struct node{int to,next;}e[N];int head[N],cnt,a[N],n,idx[N];
void add(int x,int y){e[cnt]=(node){y,head[x]};head[x]=cnt++;}
void merge(int x,int y)
{if(s[x].size()<s[y].size())swap(s[x],s[y]);for(;s[y].size();s[x].erase(s[x].begin()),s[y].erase(s[y].begin()))v.push_back(max(*s[x].begin(),*s[y].begin()));for(int i=0;i<v.size();i++)s[x].insert(v[i]);v.clear();
}
void dfs(int x)
{for(int i=head[x];i!=-1;i=e[i].next)dfs(e[i].to),merge(x,e[i].to);s[x].insert(a[x]);
}
int main()
{scanf("%d",&n);memset(head,-1,sizeof(head));for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=2,x;i<=n;i++)scanf("%d",&x),add(x,i);dfs(1);long long ans=0;while(s[1].size())ans+=*s[1].begin(),s[1].erase(s[1].begin());printf("%lld\n",ans);
}

F

不会,滚

转载于:https://www.cnblogs.com/Winniechen/p/10679565.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251941.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端vue的get和post请求

vue的get和post需要两个文件vue.js和vue-resource.js 以下是实现的代码&#xff0c;可以参考一下&#xff0c;需要注意的接口的请求需要考虑跨域的问题&#xff0c;其次就是访问页面需要在tomcat下访问&#xff0c;否则也会报跨域的问题 <!DOCTYPE html> <html lang&q…

[Vijos 1143]三取方格数

Description 设有N*N的方格图&#xff0c;我们将其中的某些方格填入正整数&#xff0c; 而其他的方格中放入0。 某人从图得左上角出发&#xff0c;可以向下走&#xff0c;也可以向右走&#xff0c;直到到达右下角。 在走过的路上&#xff0c;他取走了方格中的数。&#xff08;取…

线扫相机相关规格说明

工业线阵相机与面阵相机特点分析 点滴成海~ 2018-06-29 13:50:38 12184 收藏 29 分类专栏&#xff1a; intership 文章标签&#xff1a; 视觉元件分析 版权 最近在公司实习&#xff0c;实习中的项目是使用的是微视的一款线阵相机&#xff08;Microview MVC1024DLM-GE35&…

postgresql 不同数据库不同模式下的数据迁移

编写不容易,转载请注明出处谢谢, 数据迁移 因为之前爬虫的时候&#xff0c;一部分数据并没有上传到服务器&#xff0c;在本地。本来用的就是postgresql&#xff0c;也没用多久&#xff0c;数据迁移的时候&#xff0c;也遇到了很多问题&#xff0c;第一次使pg_dump xx > file…

Oracle中主键自增长

最近在学习Oracle和MySql&#xff0c;MySql有自动配置主键自增长auto_increment&#xff0c;这样在输入数据的时候可以不考虑主键的添加&#xff0c;方便对数据库的操作。 在Oracle中设置自增长首先用到sequence序列&#xff1b; 以创建学生表为例&#xff1a; create table St…

3.单例模式

public class Singleton {//定义私有的静态变量 private static Singleton singleton;//私有化构造函数private Singleton(){}//获取实例public static Singleton getInstance(){//同步前判断避免同步的性能损耗if(nullsingleton){//预防多线程问题synchronized(Singleton.clas…

docker与mmdetection

这里不再介绍 mmdetection 的安装和配置&#xff0c;使用 mmdetection 较简单的方法是使用已安装 mmdetection 的 docker 容器。这样直接省去了安装 mmdetection 的过程&#xff0c;让重心放在模型训练上&#xff01; 如果你对 docker 和 mmdetection 还不是很熟悉&#xff0c…

互联网平台掘金三四五线城市,你需要知道的9.9个真相

互联网上半场结束&#xff0c;一二线城市流量红利消失&#xff0c;许多互联网平台、投资机构一度经历至黑之夜。融资失败、公司倒闭、大裁员迭出。对比鲜明的是&#xff0c;深耕三四五线城市的互联网平台正在迅猛崛起。春节期间&#xff0c;小部分敏锐的业者注意到互联网产品在…

平滑重启更新(GR机制)

平滑重启更新&#xff08;GR机制&#xff09; 什么是平滑启动机制 是一种在协议重启时保证转发业务不中断的机制。什么时候用到平滑重启 平滑重启一般应用于业务更新或者版本发布过程中&#xff0c;能够避免因为代码发布重启服务导致的暂时性服务不可用的影响。ngnix 平滑重启和…

正斜杠( / )和反斜杠( \ )的区别

反斜杠“\”是电脑出现了之后为了表示程序设计里的特殊含义才发明的专用标点。所以除了程序设计领域外&#xff0c;任何地方都不应该使用反斜杠。 如何区分正反斜杠 英语&#xff1a;"/" 英文是forward slash, “\" 是backward slash形象些比喻的话&#xff0c;…

MMDetectionV2 + Colab

MMDetectionV2 Colab 超详细教程及踩坑实录 文章目录 前言一、环境配置二、准备自己的数据集 Aug.14更新三&#xff1a;修改config文件 3.1 文件结构3.2 &#xff08;本地&#xff09;修改config文件 3.2.1 &#xff08;本地&#xff09;构造自己模型的权重文件3.2.2 &#x…

刚刚,OpenStack 第 19 个版本来了,附28项特性详细解读!

刚刚&#xff0c;OpenStack 第 19 个版本来了&#xff0c;附28项特性详细解读&#xff01; OpenStack Stein版本引入了新的多云编排功能&#xff0c;以及帮助实现边缘计算用例的增强功能。 OpenStack由一系列相互关联的项目组成&#xff0c;这些项目可以以不同的组合方式组合在…

SQL作业:综合练习(二)的返评

一&#xff1a;作业题目&#xff1a;综合练习&#xff08;二&#xff09; 二&#xff1a;题目要求&#xff1a; 1、创建数据库CPXS&#xff0c;保存于E盘根目录下以自己学号姓第一个字母&#xff08;阿拉伯数字大写字母&#xff09;方式创建的文件夹中&#xff0c;初始大小5MB&…

caffe cifar10试跑问题总结

caffe cifar10试跑问题总结 [daniel] 写了一个脚本可以直接用来添加环境变量&#xff1a;/Users/songdanzju/daniel_script/export_for_ananconda.sh#! /bin/bash export PATH~/ananconda/bin:$PATH export DYLD_FALLBACK_LIBRARY_PATH~/anaconda:~/anaconda/lib:/usr/local/l…

paddlepaddle-VisualDL2.0对项目进行可视化调参

如果需要更好的阅读体验&#xff0c;可以在ai studio上fork该项目&#xff1a;使用VisualDL2.0对项目进行可视化调参 调参是深度学习必须要做的事情。数据和模型处理好后&#xff0c;需要进行模型训练&#xff0c;这个时候就需要进行调参了。一种好的参数配置&#xff0c;可以…

第一、二次实训作业

1.编写程序&#xff1a; 声明一个整型变量a&#xff0c;并赋初值5&#xff0c;在程序中判断a是奇数还是偶数&#xff0c;然后输出判断的结果。 package 判断奇偶; public class liux { public static void main(String[] args){ int x5; if(x%20){ System.out.println("这…

推荐一款作图工具

以前看到别人的时序图觉得好好看&#xff0c;然后就想这都是用的什么工具画出来的呢&#xff1f;然后看到了一个师兄用的这个工具&#xff0c;真的挺好用的。这是是试用版的界面。类图我觉着看起来效果都挺不错的。转载于:https://www.cnblogs.com/tuhooo/p/8874410.html

【codeforces】【比赛题解】#849 CF Round #431 (Div.2)

cf的比赛越来越有难度了……至少我做起来是这样。 先看看题目吧&#xff1a;点我。 这次比赛是北京时间21:35开始的&#xff0c;算是比较良心。 【A】奇数与结束 "奇数从哪里开始&#xff0c;又在哪里结束&#xff1f;梦想从何处起航&#xff0c;它们又是否会破灭呢&#…

PaddleDetection支持的数据格式

PaddleDetection支持的数据格式 目前#PaddleDetection支持43种数据格式&#xff1a;coco voc widerface。在这里我们主要说明一下如何使用自定义COCO进行目标检测、实例分割&#xff1b;如何使用自定义VOC数据集进行目标检测。在PaddleDetection新的版本中&#xff0c;我们将数…

[dts]Device Tree机制【转】

转自&#xff1a;https://www.cnblogs.com/aaronLinux/p/5496559.html 转自&#xff1a;http://blog.csdn.net/machiner1/article/details/47805069 ------------------Based on linux 3.10.24 source code 参考/documentation/devicetree/Booting-without-of.txt文档 目录 1.…