zoukankan      html  css  js  c++  java
  • [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
    ",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
    ",ans[i]);
    	return 0;
    }
    

    C.Dash Speed

    直接从边考虑似乎不可做,那么换一个角度思考,从可行的速度入手,不断往当前集合中加边,最终边集的直径就是答案。

    这种做法与某次考试的T2十分类似。

    以速度为下标建立一棵线段树,并把符合区间限制的边插入(方式类似于前向星,或者直接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!
    ");system("pause");for (;;);exit(0);}
            }
            return *p1++;
        }
        inline bool blank(char ch){return ch==' '||ch=='
    '||ch=='
    '||ch=='	';}
        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('
    ');
            }
            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('
    ');
            }
            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('
    ');}
            void print(char *s){while (*s)out(*s++);}
            void println(char *s){while (*s)out(*s++);out('
    ');}
            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('
    ');}
        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('
    ');}
        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;
    }
    
  • 相关阅读:
    C#中属性和字段的区别
    利用原生态的(System.Web.Extensions)JavaScriptSerializer将mvc 前台提交到controller序列化复杂对象
    点击图片后放大居中显示
    Python logging模块
    MySQL免安装版 配置
    python 字符串 常用方法
    python 格式化输出
    欢迎使用CSDN-markdown编辑器
    Program received signal SIGSEGV, Segmentation fault.
    error MSB6006: “CL.exe”已退出,代码为 -1073741502。
  • 原文地址:https://www.cnblogs.com/Rorschach-XR/p/11622417.html
Copyright © 2011-2022 走看看