[CSP-S模拟测试58]题解
以后题解还是单独放吧。
A.Divisors
根号筛求所有数的因子,扫一遍去重统计即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
const int N=205;
int a[N],m,n;
map<int,int> bu;
vector<int> res,app;
int ans[N];
int main()
{
//freopen("dt.in","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d",&a[i]);
for(int j=1;1LL*j*j<=a[i];j++)
{
if(a[i]%j)continue;
if(j*j==a[i])res.push_back(j);
else res.push_back(j),res.push_back(a[i]/j);
}
}
int sz=res.size();
for(int i=0;i<sz;i++)
{
if(res[i]>n)continue;
if(bu.find(res[i])==bu.end())app.push_back(res[i]);
bu[res[i]]++;
}
sz=app.size();
for(int i=0;i<sz;i++)
ans[bu[app[i]]]++;
ans[0]=n-sz;
for(int i=0;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
B.Market
离线询问。把询问和商店都按时间排序,维护一个指针把所有能被当前计划购买的商品都放进来跑一次背包。
注意到话费很大而价值很小,那么把价值作为dp数组下标,后缀取min保证单调后二分查找最优解即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int inf=0x3f3f3f3f;
int n,m,f[100005],ans[100005];
struct shop
{
int c,v,t;
friend bool operator < (shop a,shop b)
{
return a.t<b.t;
}
}s[305];
struct plan
{
int t,num,id;
friend bool operator < (plan a,plan b)
{
return a.t<b.t;
}
}p[100005];
void show()
{
for(int i=1;i<=n*300;i++)
cout<<f[i]<<endl;
}
int main()
{
/*freopen("dt.in","r",stdin);
freopen("my.out","w",stdout);*/
n=read();m=read();
for(int i=1;i<=n;i++)
s[i].c=read(),s[i].v=read(),s[i].t=read();
for(int i=1;i<=m;i++)
p[i].t=read(),p[i].num=read(),p[i].id=i;
sort(s+1,s+n+1);sort(p+1,p+m+1);
memset(f,0x3f,sizeof(f));
f[0]=0;
int j=1;
for(int i=1;i<=m;i++)
{
while(j<=n&&s[j].t<=p[i].t)
{
for(int k=n*300;k>=s[j].v;k--)
f[k]=min(f[k],f[k-s[j].v]+s[j].c);
for(int k=n*300;k;k--)
f[k]=min(f[k],f[k+1]);
j++;
}
//ow();
//cout<<p[i].id<<' '<<p[i].num<<endl;
ans[p[i].id]=upper_bound(f+1,f+n*300+1,p[i].num)-f-1; }
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
C.Dash Speed
直接从边考虑似乎不可做,那么换一个角度思考,从可行的速度入手,不断往当前集合中加边,最终边集的直径就是答案。
以速度为下标建立一棵线段树,并把符合区间限制的边插入(方式类似于前向星,或者直接vector也行)。
之后就可以通过$O(n\ log\ n)$的线段树分治一次性得到所有答案。到达一个线段树区间时,将存在这里的边所连接的点集合并。具体合并方式就是像之前那道题一样,讨论6种情况来确定新联通块端点。
由于分治需要回溯,回溯需要撤销影响,所以并查集的结构不能中途发生不可逆改变,即不能路径压缩。那么这里就需要另外一种合并方式——按秩合并。
之后用栈记录一下改变的信息,回溯时弹栈撤销即可。
#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<cmath>
#define re register
using namespace std;
namespace IO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(int &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(ll &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}
inline void read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x;
}
inline void read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror)return;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(ll x){Ostream.print(x);}
inline void println(ll x){Ostream.println(x);}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
const int N=1e5+5;
int n,m;
int to[N<<4],head[N<<4],nxt[N<<4],tot,fr[N<<4];
int fa[N],size[N],son[N],Top[N],dep[N],ans[N];
vector<int> g[N];
#define ls(k) (k)<<1
#define rs(k) (k)<<1|1
struct Stack
{
int x,y,op,nd1,nd2;
}s[N<<4];
int top;
void ins(int k,int l,int r,int L,int R,int x,int y)
{
if(L<=l&&R>=r)
{
to[++tot]=y;fr[tot]=x;
nxt[tot]=head[k];head[k]=tot;
return ;
}
int mid=l+r>>1;
if(L<=mid)ins(ls(k),l,mid,L,R,x,y);
if(R>mid)ins(rs(k),mid+1,r,L,R,x,y);
}
void dfs1(int x,int f)
{
size[x]=1;fa[x]=f;
int sz=g[x].size();
for(int i=0;i<sz;i++)
{
int y=g[x][i];
if(y==f)continue;
dep[y]=dep[x]+1;
dfs1(y,x);
size[x]+=size[y];
if(size[y]>size[son[x]])son[x]=y;
}
return ;
}
void dfs2(int x,int f)
{
Top[x]=f;
if(!son[x])return ;
dfs2(son[x],f);
int sz=g[x].size();
for(int i=0;i<sz;i++)
{
int y=g[x][i];
if(!Top[y])dfs2(y,y);
}
} int lca(int x,int y)
{
while(Top[x]!=Top[y])
{
if(dep[Top[x]]<dep[Top[y]])swap(x,y);
x=fa[Top[x]];
//cout<<x<<' '<<y<<endl;
}
return dep[x]<dep[y]?x:y;
}
int dis(int x,int y)
{
return dep[x]+dep[y]-(dep[lca(x,y)]<<1);
} namespace U
{
int fa[N],node[N][3],rk[N];
void ini()
{
for(int i=1;i<=n;i++)
fa[i]=node[i][0]=node[i][1]=i;
}
int findf(int x)
{
return fa[x]==x?x:findf(fa[x]);
}
void merge(int xx,int yy,int &d)
{
int x=findf(xx),y=findf(yy),nd1,nd2,maxd=-1,nowd=dis(node[x][0],node[x][1]);
if(nowd>maxd)maxd=nowd,nd1=node[x][0],nd2=node[x][1];
nowd=dis(node[y][0],node[y][1]);
if(nowd>maxd)maxd=nowd,nd1=node[y][0],nd2=node[y][1];
for(re int i=0;i<2;i++)
for(re int j=0;j<2;j++)
{
nowd=dis(node[x][i],node[y][j]);
if(nowd>maxd)maxd=nowd,nd1=node[x][i],nd2=node[y][j];
}
d=max(d,maxd);
if(rk[x]<rk[y])swap(x,y);
s[++top]=(Stack){x,y,0,node[x][0],node[x][1]};
if(rk[x]==rk[y])++rk[x],s[top].op=1;
fa[y]=x;node[x][0]=nd1;node[x][1]=nd2;
}
}
void cancel(int k)
{
while(top>k)
{
U::rk[s[top].x]-=s[top].op;
U::fa[s[top].y]=s[top].y;
U::node[s[top].x][0]=s[top].nd1;
U::node[s[top].x][1]=s[top].nd2;
top--;
}
}
void work(int k,int l,int r,int sum)
{
int pos=top;
for(re int i=head[k];i;i=nxt[i])
U::merge(fr[i],to[i],sum);
if(l==r)
{
ans[l]=sum;
cancel(pos);
return ;
}
int mid=l+r>>1;
work(ls(k),l,mid,sum);
work(rs(k),mid+1,r,sum);
cancel(pos);
}
int main()
{
//freopen("speed2.in","r",stdin);
IO::read(n);IO::read(m);
for(re int i=1;i<n;i++)
{
int x,y,l,r;
IO::read(x);IO::read(y);
IO::read(l);IO::read(r);
g[x].push_back(y);
g[y].push_back(x);
ins(1,1,n,l,r,x,y);
}
dep[1]=1;
dfs1(1,0);dfs2(1,1);
/*for(int i=1;i<=n;i++)
cout<<i<<' '<<size[i]<<' '<<son[i]<<' '<<Top[i]<<endl;*/
U::ini();
work(1,1,n,0);
while(m--)
{
int q;
IO::read(q);
IO::println(ans[q]);
}
return 0;
}
[CSP-S模拟测试58]题解的更多相关文章
- [考试反思]1003csp-s模拟测试58:沉淀
稳住阵脚. 还可以. 至少想拿到的分都拿到了,最后一题的确因为不会按秩合并和线段树分治而想不出来. 对拍了,暴力都拍了.挺稳的. 但是其实也有波折,险些被卡内存. 如果内存使用不连续或申请的内存全部使 ...
- CSP-S 模拟测试94题解
T1 yuuustu: 可以对两边取对数,然后就转化为两个double的比较,时间复杂度$O(n)$ 然后我就用神奇0.4骗分水过 #include<bits/stdc++.h> usin ...
- CSP-S模拟测试 88 题解
T1 queue: 考场写出dp柿子后觉得很斜率优化,然后因为理解错了题觉得斜率优化完全不可做,只打了暴力. 实际上他是可以乱序的,所以直接sort,正确性比较显然,贪心可证,然后就是个sb斜率优化d ...
- CSP-S 模拟测试92 题解
话说我怎么觉得我没咕多长时间啊,怎么就又落了20多场题解啊 T1 array: 根据题意不难列出二元一次方程,于是可以用exgcd求解,然而还有一个限制条件就是$abs(x)+abs(y)$最小,这好 ...
- CSP-S 模拟测试57题解
人生第一次A,B层一块考rank2,虽然说分差没几分,但还是值得纪念. 题解: T1 天空龙: 大神题,因为我从不写快读也没有写考场注释的习惯,所以不会做,全hzoi就kx会做,kx真大神级人物. T ...
- CSP-S 模拟测试 51 题解
考试过程: 惯例先看一遍三道题,T1 一开始反应要求割点,但是这是有向图,肯定不能求割点,康了一下数据范围,有40%是树的,还不错,决定待会在打. 看T2 字符串题,完了我字符串最弱了,肯定只能打暴力 ...
- CSP-S 模拟测试 45 题解
由于咕掉的题解太多了,所以只能趁改完不动题的时间,来补补坑qwq,还是太弱了. 考试过程: 到新机房的第一次考试,貌似海星? 第一题一开始就觉得是个贪心,但以为所有小怪兽都要打完,所以想复杂了,但后来 ...
- [CSP-S模拟测试97]题解
A.小盆友的游戏 感觉题解解释的很牵强啊……还是打表找规律比较靠谱 对于每个人,它构造了一个期望函数$f(x)$,设它的跟班个数为$cnt[x]$,那么令$f(x)=2^{cnt[x]}-1$(??鬼 ...
- [CSP-S模拟测试96]题解
以后不能再借没改完题的理由不写题解了…… A.求和 求$\sum \sum i+j-1$ 柿子就不化了吧……这年头pj都不考这么弱智的公式化简了…… 坑点1:模数不定,可能没有2的逆元,那么只要先把乘 ...
随机推荐
- Java总结第二期
大家好,我又来了!!啦啦,我知道你们很想我,很想我赶快写更多的文章来提高自己的水平,好吧,我就从了你们.下面跟我一起来光顾Java第二期,掌声,掌声!!! 第二章: 这章,我要给大家讲得内容有变量,常 ...
- vue.js中created()与activated()的个人使用理解
created():在创建vue对象时,当html渲染之前就触发:但是注意,全局vue.js不强制刷新或者重启时只创建一次,也就是说,created()只会触发一次:这时候只有dom没有数据挂载. a ...
- meta标签 使用说明(http-equiv、refresh、seo)
meta标签 使用说明(http-equiv.refresh.seo) meta标签,是在head标签里面,一般用做页面描述的.它的内容,用来描述页面一些信息的,如类型.编码.作者.简介等!虽然,它不 ...
- github 上的PHP资源大全
依赖管理 ——用于依赖管理的包和框架Composer/Packagist : 一个包和依赖管理器Composer Installers: 一个多框架Composer库安装器Pickle: 可以在任意 ...
- Java程序员必精通之—synchronized
更多Java并发文章:https://www.cnblogs.com/hello-shf/category/1619780.html 一.简介 相信每一个java程序员对synchronized都不会 ...
- Oracle基础数据类型与运算符
Oracle基础数据类型: 1. 字符型:字符串 char(最大2000), nchar(最大1000, 支持 Unicode)--->固定长 ...
- 从FreeBSD里面看到的网络协议列表,感觉可以保存一下
# # Internet protocols # # $FreeBSD$ # from: @(#)protocols 5.1 (Berkeley) 4/17/89 # # See also http: ...
- jQuery学习笔记(基础部分)
参考:菜鸟教程 一.简介 1.jQuery 是一个 JavaScript 库. 2.jQuery的版本:压缩版(用户生成)和未压缩(用于测试和开发) 3.jQuery的引入方式: 从http://jq ...
- spring集成rabbitMq(非springboot)
首先 , pom文件需要加入spring集成rabbitMq的依赖: <dependency> <groupId>org.springframework.amqp</gr ...
- Android中Parcelable的原理和使用方法
Parcelable的简单介绍 介绍Parcelable不得不先提一下Serializable接口,Serializable是Java为我们提供的一个标准化的序列化接口,那什么是序列化呢? 进行And ...