以后题解还是单独放吧。
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; }
原文地址:https://www.cnblogs.com/Rorschach-XR/p/11622417.html
时间: 2024-11-05 23:28:08