HGOI 20191031am 题解
分类:
IT文章
•
2025-01-02 19:37:01
Problem A Divisors
给出$m$个不同的正整数$a_i$,设数论函数 $f(k) = sumlimits_{i = 1}^{n} [(sumlimits_{j = 1}^{m} [a_j | i] )== k]$
其中$b|a$表示$a$是$b$的因数,对于所有$k in [0,m]$,输出答案。
对于$100\%$的数据满足$nleq 200 , a_i leq 10^9$
Solution :
如果我们已知$sumlimits_{i = 1}^{m} f(i)$,那么显然$f(0) = n - sumlimits_{i = 1}^{m} f(i)$。
考虑到如果$j in [1,n]$是任意一个$a_i$的因数的时候,它一定被所有$a_i$因数的集合包含。
因为除去这个集合的其他$[1,n]$的数字,必然对$f(0)$贡献。
所以,直接对于每个数暴力出它的所有因数,构出这个集合$S$。其中$|S| = 2 msumlimits_{i = 1}^{m} sqrt{a_i}$
对该集合去重后暴力处理出$f(1) ... f(m)$,那么$f(0) = n - sumlimits_{i = 1}^{m} f(i) $可以方便出解。
总时间复杂度为$O(m^2sumlimits_{i = 1}^{m} sqrt{a_i})$
# include <bits/stdc++.h>
using namespace std;
const int N=205;
int n,m,a[N],ans[N];
vector<int>tmp;
void work(int x) {
for (int i=1;i*i<=x;i++) if (x%i==0) {
tmp.push_back(i); tmp.push_back(x/i);
}
}
int calc(int x) {
int t = 0;
for (int i=1;i<=m;i++) if (a[i] % x == 0) t++;
return t;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++) {
int t; scanf("%d",&t); work(t);
a[i] = t;
}
sort(tmp.begin(),tmp.end());
tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());
for (int i=0;i<tmp.size();i++) if (tmp[i]<=n) {
ans[calc(tmp[i])]++;
}
ans[0]=n;
for (int i=1;i<=m;i++) ans[0]-=ans[i];
for (int i=0;i<=m;i++) printf("%d
",ans[i]);
return 0;
}
div.cpp
Problem B Marke
有$n$个商店,每个商店某一时刻$r_i$及以后会卖$1$种物品且只有$1$个。
每个物品有花费$c_i$和价值$v_i$, 处理$m$个询问,表示在$t_i$时刻购买所有物品且有钱数$w_i$。
输出当前限制的最大价值。
对于$100\%$的数据满足$1 leq n leq 300, 1 leq m leq 10^5, 1 leq c_i,w_i leq 10^9, 1 leq r_i , t_i leq 300$
Solution :
表面上看是一个$m$个询问的$0/1$背包,事实上我们观察到$t_i$的值非常的小。
考虑将询问按照时间$t_i$离线。每个时刻如遇到一个商店新开放就更新掉$dp$数组,对后面的询问造成影响。
由于$c_i$的值到达了$10^9$级别而对应的贡献却比较小,只有$300$,所以我们设$f[i]$表示达到至少$i$的贡献最少的钱数。
总贡献不会超过$300^2$,共有$n$次插入,每次插入只要倒序更新一遍$f$数组即可(这样就满足$01$背包的限制)。
时间复杂度是$O(n^2 max{w_i})$
# include <bits/stdc++.h>
using namespace std;
const int N=305,M=300*300+10,Q=1e5+10;
int n,m,f[M],res[Q];
vector< pair<int,int> >r[N],q[N];
int main()
{
scanf("%d%d",&n,&m);
int Max = 0;
for (int i=1;i<=n;i++) {
int c,v,t; scanf("%d%d%d",&c,&v,&t);
r[t].push_back(make_pair(c,v));
Max = max(Max,t);
}
for (int i=1;i<=m;i++) {
int t,v; scanf("%d%d",&t,&v);
q[t].push_back(make_pair(v,i));
Max = max(Max,t);
}
memset(f,0x3f,sizeof(f)); f[0]=0;
for (int i=1;i<=Max;i++) {
if (r[i].size()) {
for (int j=0;j<r[i].size();j++) {
int c=r[i][j].first,v=r[i][j].second;
for (int k=90000;k>=v;k--) f[k]=min(f[k],f[k-v]+c);
for (int k=90000;k>=0;k--) f[k]=min(f[k],f[k+1]);
}
}
if (q[i].size()) {
for (int j=0;j<q[i].size();j++) {
int l=0,r=90000,ans;
int M=q[i][j].first,id=q[i][j].second;
while (l<=r) {
int mid = (l+r)>>1;
if (f[mid]<=M) ans=mid,l=mid+1;
else r=mid-1;
}
res[id] = ans;
}
}
}
for (int i=1;i<=m;i++) printf("%d
",res[i]);
return 0;
}
market.cpp
# pragma GCC optimize(2)
# pragma GCC optimize(3)
# include<bits/stdc++.h>
using namespace std;
const int N=70000+100;
int n,m;
struct RRR { int a,b,c,d;}input[N];
int qestion[N];
namespace Subtask1 { //无脑暴力
int tot,speed;
int head[N];
struct rec{ int pre,to,l,r;}a[N<<1];
void adde(int u,int v,int l,int r) {
a[++tot].pre=head[u];
a[tot].to=v;
a[tot].l=l;
a[tot].r=r;
head[u]=tot;
}
int ans;
void dfs(int u,int fa,int L) {
ans=max(ans,L);
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to;
if (v==fa||speed>a[i].r||speed<a[i].l) continue;
dfs(v,u,L+1);
}
}
void main() {
int now=1;
for (int i=2;i<=n;i++) {
int u=input[now].a,v=input[now].b,l=input[now].c,r=input[now].d;
adde(u,v,l,r); adde(v,u,l,r);
now++;
}
now=1;
while (m--) {
speed=qestion[now];
ans = 0; for (int i=1;i<=n;i++) dfs(i,0,0);
printf("%d
",ans);
now++;
}
}
}
namespace Subtask2 { //链的情况
int ans[N];
vector< pair<int,int> >r[N];
vector< int >q[N];
# define lson ls,l,mid
# define rson rs,mid+1,r
# define mid (l+r>>1)
# define ls (x<<1)
# define rs (x<<1|1)
struct Seg {
int lans,rans,ret;
}tr[N<<2];
void build(int x,int l,int r) {
if (l == r) {
tr[x].lans = tr[x].rans= tr[x].ret = 0;
return;
}
build(lson); build(rson);
tr[x].ret=max(max(tr[ls].ret,tr[ls].rans+tr[rs].lans),tr[rs].ret);
if (tr[ls].lans==mid-l+1) tr[x].lans=tr[ls].lans+tr[rs].lans;
else tr[x].lans=tr[ls].lans;
if (tr[x].rans==r-mid) tr[x].rans=tr[rs].rans+tr[ls].rans;
else tr[x].rans=tr[rs].rans;
}
void update(int x,int l,int r,int pos,int da) {
if (l == r) {
tr[x].lans = tr[x].rans= tr[x].ret = da;
return;
}
if (pos<=mid) update(lson,pos,da);
else update(rson,pos,da);
tr[x].ret=max(max(tr[ls].ret,tr[ls].rans+tr[rs].lans),tr[rs].ret);
if (tr[ls].lans==mid-l+1) tr[x].lans=tr[ls].lans+tr[rs].lans;
else tr[x].lans=tr[ls].lans;
if (tr[rs].rans==r-mid) tr[x].rans=tr[rs].rans+tr[ls].rans;
else tr[x].rans=tr[rs].rans;
}
void main() {
int now=1;
for (int i=2;i<=n;i++) {
int u=input[now].a,v=input[now].b,ll=input[now].c,rr=input[now].d;
r[ll].push_back(make_pair(u,1));
r[rr+1].push_back(make_pair(u,0));
now++;
}
now=1;
for (int i=1;i<=m;i++) {
int speed = qestion[now];
q[speed].push_back(i);
now++;
}
build(1,1,n);
for (int i=1;i<=n;i++) {
if (r[i].size()) {
for (int j=0;j<r[i].size();j++)
update(1,1,n,r[i][j].first,r[i][j].second);
}
if (q[i].size()) {
for (int j=0;j<q[i].size();j++)
ans[q[i][j]]=tr[1].ret;
}
}
for (int i=1;i<=m;i++) printf("%d
",ans[i]);
}
}
namespace Subtask3 { //l_i = 1的情况
struct rec{ int pre,to;}a[N<<1];
struct QwQ{ int s,t;}r[N];
vector< pair<int,int> >ee;
vector<int>qes[N];
int tot;
int g[N][18];
int head[N],p[N],val[N],f[N],dep[N],an[N];
int del[N],ans[N];
void adde(int u,int v) {
a[++tot].pre=head[u];
a[tot].to=v;
head[u]=tot;
}
bool cmp(int x,int y) { return val[x]<val[y];}
void dfs(int u,int fa) {
dep[u] = dep[fa]+1;
g[u][0] = fa;
for (int i=head[u];i;i=a[i].pre) {
int v=a[i].to; if (v==fa) continue;
dfs(v,u);
}
}
int lca(int u,int v) {
if (dep[u] < dep[v]) swap(u,v);
for (int i=17;i>=0;i--)
if (dep[g[u][i]]>=dep[v]) u=g[u][i];
if (u == v) return u;
for (int i=17;i>=0;i--)
if (g[u][i]!=g[v][i]) u=g[u][i],v=g[v][i];
return g[u][0];
}
int dist(int u,int v) {
return dep[u]+dep[v]-2*dep[lca(u,v)];
}
int father(int x) {
if (f[x]==x) return x;
return f[x]=father(f[x]);
}
int tr[N<<2];
# define lson ls,l,mid
# define rson rs,mid+1,r
# define mid (l+r>>1)
# define ls (x<<1)
# define rs (x<<1|1)
void build(int x,int l,int r) {
if (l == r) { tr[x]=1; return;}
build(lson); build(rson);
tr[x]=max(tr[ls],tr[rs]);
}
void update(int x,int l,int r,int pos,int val) {
if (l == r) { tr[x] = val; return;}
if (pos <= mid) update(lson,pos,val);
else update(rson,pos,val);
tr[x]=max(tr[ls],tr[rs]);
}
void main()
{
ee.push_back(make_pair(0,0));
int now=1;
for (int i=2;i<=n;i++) {
int u=input[now].a,v=input[now].b,l=input[now].c,r=input[now].d;
ee.push_back(make_pair(u,v));
adde(u,v); adde(v,u); val[i-1]=r;
del[r+1]++;
now++;
}
dfs(1,0);
for (int i=1;i<=17;i++)
for (int j=1;j<=n;j++)
g[j][i]=g[g[j][i-1]][i-1];
build(1,1,n);
for (int i=1;i<=n-1;i++) p[i]=i;
sort(p+1,p+n,cmp);
for (int i=1;i<=n;i++) { f[i]=i; r[i].s=r[i].t=i;}
an[n]=0;
for (int i=n-1;i>=1;i--) {
int u=ee[p[i]].first,v=ee[p[i]].second;
int fa_u=father(u),fa_v=father(v);
int s1=r[fa_u].s,t1=r[fa_u].t;
int s2=r[fa_v].s,t2=r[fa_v].t;
int d1=dist(s1,t1),d2=dist(s1,s2),d3=dist(s1,t2);
int d4=dist(t1,s2),d5=dist(t1,t2),d6=dist(s2,t2);
int op=1;
if (d2>d1) d1=d2,op=2;
if (d3>d1) d1=d3,op=3;
if (d4>d1) d1=d4,op=4;
if (d5>d1) d1=d5,op=5;
if (d6>d1) d1=d6,op=6;
update(1,1,n,fa_u,0);
f[fa_u] = fa_v;
if (op==1) {
r[fa_v].s=s1, r[fa_v].t=t1;
}else if (op==2) {
r[fa_v].s=s1, r[fa_v].t=s2;
}else if (op==3) {
r[fa_v].s=s1, r[fa_v].t=t2;
}else if (op==4) {
r[fa_v].s=t1, r[fa_v].t=s2;
}else if (op==5) {
r[fa_v].s=t1, r[fa_v].t=t2;
}else {
r[fa_v].s=s2, r[fa_v].t=t2;
}
update(1,1,n,fa_v,dist(r[fa_v].s,r[fa_v].t));
an[i]=tr[1];
}
now=1;
for (int i=1;i<=m;i++) {
int v = qestion[now];
qes[v].push_back(i);
now++;
}
now=1;
for (int i=1;i<=n;i++) {
now+=del[i];
if (qes[i].size()) {
for (int j=0;j<qes[i].size();j++)
ans[qes[i][j]]=an[now];
}
}
for (int i=1;i<=m;i++) printf("%d
",ans[i]);
}
}
int main()
{
scanf("%d%d",&n,&m);
bool flag = 1;
for (int i=1;i<=n-1;i++) {
scanf("%d%d%d%d",&input[i].a,&input[i].b,&input[i].c,&input[i].d);
if (input[i].b != input[i].a+1) flag=0;
}
for (int i=1;i<=m;i++) {
scanf("%d",&qestion[i]);
}
if (n<=20 && m<=20) {
Subtask1::main(); exit(0);
} else if (flag) {
Subtask2::main(); exit(0);
} else {
Subtask3::main(); exit(0);
}
return 0;
}