zoukankan      html  css  js  c++  java
  • CF 1313

    偷偷摸一套题解。。。

    CF 1313

    A

    给定三个颜色的数量,问能凑出多少钟不同的搭配

    贪心,先拿最多的颜色搭配出需要颜色最少的组合

        #include<bits/stdc++.h>
        using namespace std;
        namespace red{
        #define int long long
        	inline int read()
        	{
        		int x=0;char ch,f=1;
        		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        		if(ch=='-') f=0,ch=getchar();
        		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 
        		return f?x:-x;
        	}
        	const int N=1e5+10,p=998244353;
        	int haku;
        	int a[4],sum;
        	inline void main()
        	{
        		haku=read();
        		while(haku--)
        		{
        			a[1]=read(),a[2]=read(),a[3]=read();
        			sort(a+1,a+4);
        			sum=0;
        			if(a[1]) --a[1],++sum;
        			if(a[2]) --a[2],++sum;
        			if(a[3]) --a[3],++sum;
        			if(a[2]&&a[3]) --a[2],--a[3],++sum;
        			if(a[1]&&a[3]) --a[1],--a[3],++sum;
        			if(a[1]&&a[2]) --a[1],--a[2],++sum;
        			if(a[1]&&a[2]&&a[3]) ++sum;
        			printf("%lld
    ",sum);
        		}
        	}
        }
        signed main()
        {
        	red::main();
        	return 0;
        }
    

    B

    最小排名:尽量让其他的人(sum=x+y+1),有些第一轮的数字做不到就让这些数字先把第二轮最小的浪费掉,得到排名(=max(1,x+y-n+1))

    最大排名:尽量让其他人(sum=x+y),做不到的同理花掉最小的数字,得到排名(=min(n,z-1))

    (x==1,y==1)(x==n,y==n) 的时候都要特判。。

        #include<bits/stdc++.h>
        using namespace std;
        namespace red{
        #define int long long
        	inline int read()
        	{
        		int x=0;char ch,f=1;
        		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        		if(ch=='-') f=0,ch=getchar();
        		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 
        		return f?x:-x;
        	}
        	const int N=1e5+10,p=998244353;
        	int haku;
        	int n,x,y,z;
        	inline void main()
        	{
        		haku=read();
        		while(haku--)
        		{
        			n=read(),x=read(),y=read();
        			if(x==1&&y==1)
        			{
        				puts("1 1");
        				continue;
        			}
        			if(x==n&&y==n)
        			{
        				printf("%lld %lld
    ",n,n);
        				continue;
        			}
        			z=x+y;
        			if(x>y) swap(x,y);
        			int sum1=0,sum2=0;
        			sum1=max(1ll,z-n+1);
        			sum2=min(z-1,n);
        			printf("%lld %lld
    ",sum1,sum2);
        		}
        	}
        }
        signed main()
        {
        	red::main();
        	return 0;
        }
        /*
        1
        5 5 1
         
        */
    

    C

    (s1[i])表示以(i)为峰,(1-i)的和,(s2[i])表示以(i)为峰,(i-n)的和,枚举中间点拼接一下

    记得打完暴力打正解的时候把数组开大。。

        #include<bits/stdc++.h>
        using namespace std;
        namespace red{
        #define int long long
            inline int read()
            {
            	int x=0;char ch,f=1;
            	for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
            	if(ch=='-') f=0,ch=getchar();
            	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 
            	return f?x:-x;
            }
            const int N=5e5+10,p=998244353;
            int haku;
            int n,sum,ret,pos;
            int a[N],c[N];
            int st[N],top;
            int s1[N],s2[N];
            inline void main()
            {
            	n=read();
            	for(int i=1;i<=n;++i) a[i]=read();
            	for(int i=1;i<=n;++i)
            	{
            		s1[i]=s1[i-1];
            		while(top&&a[i]<=a[st[top]])
            		{
            			s1[i]-=(st[top]-st[top-1])*a[st[top]];
            			--top;
            		}
            		s1[i]+=(i-st[top])*a[i];
            		st[++top]=i;
            	}
            	st[top=0]=n+1;
            	for(int i=n;i;--i)
            	{
           			s2[i]=s2[i+1];
            		while(top&&a[i]<=a[st[top]])
            		{
            			s2[i]-=(st[top-1]-st[top])*a[st[top]];
            			--top;
            		}
            		s2[i]+=(st[top]-i)*a[i];
            		st[++top]=i;
            	}
            	for(int i=0;i<=n;++i)
            	{
            		if(s1[i]+s2[i+1]>ret)
            		{
            			pos=a[i]>a[i+1]?i:i+1;
            			ret=s1[i]+s2[i+1];
            		}
            	}
            	c[pos]=a[pos];
            	for(int i=pos-1;i;--i) c[i]=min(a[i],c[i+1]);
            	for(int i=pos+1;i<=n;++i) c[i]=min(a[i],c[i-1]);
            	for(int i=1;i<=n;++i) printf("%lld ",c[i]); 
            }
        }
        signed main()
        {
           	red::main();
           	return 0;
        }
    

    D

    每个区间只会被覆盖(k)次,撞鸭一个区间被哪些线段覆盖,(f[i][s])表示区间([i,i+1])被s种线段覆盖后的最大价值

        #include<bits/stdc++.h>
        using namespace std;
        namespace red{
        #define int long long
        #define ls(p) (p<<1)
        #define rs(p) (p<<1|1)
        #define mid ((l+r)>>1)
        	inline int read()
        	{
        		int x=0;char ch,f=1;
        		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
        		if(ch=='-') f=0,ch=getchar();
        		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 
        		return f?x:-x;
        	}
        	const int N=2e5+10,inf=1e9+7;
        	int n,m,k,s,now,ret;
        	int c[N],num;
        	int f[N],cnt[N];
        	int l[N],r[N],id[N]; 
        	vector<int> d[N];
        	inline void main()
        	{
        		n=read(),m=read(),k=read();s=1<<k;
        		for(int i=1;i<s;++i) cnt[i]=cnt[i>>1]+(i&1);
        		for(int i=1;i<=n;++i)
        		{
        			l[i]=read(),r[i]=read()+1;
        			c[++num]=l[i],c[++num]=r[i];
        		}
        		c[++num]=m;c[++num]=1;
        		sort(c+1,c+num+1);num=unique(c+1,c+num+1)-c-1;
        		for(int i=1;i<=n;++i)
        		{
        			l[i]=lower_bound(c+1,c+num+1,l[i])-c;
        			r[i]=lower_bound(c+1,c+num+1,r[i])-c;
        			for(int j=l[i];j<r[i];++j) d[j].push_back(i);
        		}
        		memset(f,0xcf,sizeof(f));f[0]=0;
        		for(int i=1;i<num;++i)
        		{
        			for(int j=0;j<k;++j)
        				if(id[j]&&r[id[j]]<=i) now^=1<<j,id[j]=0;
        			for(int j=0;j<s;++j)
        				if((j|now)!=now) f[j&now]=max(f[j&now],f[j]),f[j]=-inf;
        			for(int j=0;j<d[i].size();++j) if(l[d[i][j]]==i)
        			{
        				for(int p=0;p<k;++p) if(!id[p])
        				{
        					for(int l=s-1;~l;--l)
        					{
        						f[l|1<<p]=f[l];
        					}
        					id[p]=d[i][j],now|=1<<p;break;
        				}
        			}
        			for(int j=0;j<s;++j)
        				f[j]+=(cnt[j]&1)*(c[i+1]-c[i]);
        		}
        		for(int i=0;i<s;++i) ret=max(ret,f[i]);
        		printf("%lld
    ",ret);
        	}
        }
        signed main()
        {
        	red::main();
        	return 0;
        }
    

    E

    (f[i])表示(a)串以(i)开头与(s)串的最长公共前缀,(g[i])表示(b)串以(i)结尾与(s)串的最长公共后缀

    由于两个区间必须有交,所以(l_1<=r_2)

    由于两个区间长度之和等于(m),所以(r_2<=l_1+m-2)

    对于一对固定的(l_1,r_2),对答案的贡献为(f[l_1]=g[r_2]-m+1)

    [ret=sumlimits_{i=1}^{n}sumlimits_{j=i}^{min(n,i+m+2)}max(f[i]+g[j]-m+1,0) ]

    我们开两个(bit),用来记录([i,i+m-2])(g[j])的数量和加和

    显然对于(g[j]+1<m-f[i])的部分我们是不需要的,我们每次先对答案加上([m-f[i],m])区间内的(g[j])的和

    再加上 (数量*(f[i]-m+1))

    #include<bits/stdc++.h>
    using namespace std;
    namespace red{
    #define int long long
    #define ls(p) (p<<1)
    #define rs(p) (p<<1|1)
    #define mid ((l+r)>>1)
    	inline int read()
    	{
    		int x=0;char ch,f=1;
    		for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
    		if(ch=='-') f=0,ch=getchar();
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} 
    		return f?x:-x;
    	}
    	const int N=1e6+10,inf=1e9+7,base=131,mod=1e9+7;
    	int n,m,t,ret;
    	char a[N],b[N],s[N];
    	int nxt[N],f[N],g[N];
    	int pw[N],ha[N],hs[N];
    	inline void prepare(char *a,int *f)
    	{
    		int len=max(n,m);
    		for(int i=pw[0]=1;i<=len;++i) pw[i]=pw[i-1]*base%mod;
    		for(int i=1;i<=n;++i) ha[i]=(ha[i-1]*base+a[i])%mod;
    		for(int i=1;i<=m;++i) hs[i]=(hs[i-1]*base+s[i])%mod;
    		for(int i=1;i<=n;++i)
    		{
    			int l=i,r=n;
    			while(l<=r)
    			{
    				int t1=(ha[mid]-ha[i-1]*pw[mid-i+1]%mod+mod)%mod;
    				int t2=hs[mid-i+1];
    				if(t1==t2) f[i]=mid-i+1,l=mid+1;
    				else r=mid-1;
    			}
    			f[i]=min(f[i],m-1);
    		}
    	}
    	struct BIT
    	{
    		int tr[N];
    		BIT(){memset(tr,0,sizeof(tr));}
    		inline void update(int p,int k)
    		{
    			for(p++;p<N;p+=p&(-p)) tr[p]+=k;
    		}
    		inline int query(int p)
    		{
    			int ret=0;
    			for(p++;p;p-=p&(-p)) ret+=tr[p];
    			return ret;
    		}
    	}bit[2];
    	inline void main()
    	{
    		n=read(),m=read();
    		scanf("%s%s%s",a+1,b+1,s+1);
    		prepare(a,f);
    		reverse(s+1,s+m+1);reverse(b+1,b+n+1);
    		prepare(b,g);
    		reverse(g+1,g+n+1);
    		for(int i=n;i;--i)
    		{
    			bit[0].update(g[i],1);
    			bit[1].update(g[i],g[i]);
    			if(i+m-1<=n)
    			{
    				bit[0].update(g[i+m-1],-1);
    				bit[1].update(g[i+m-1],-g[i+m-1]);
    			}
    			int v=m-f[i];
    			ret+=bit[1].query(m)-bit[1].query(v-1);
    			ret-=(bit[0].query(m)-bit[0].query(v-1))*(v-1);
    		}
    		printf("%lld
    ",ret);
    	}
    }
    signed main()
    {
    	red::main();
    	return 0;
    }
    
  • 相关阅读:
    关于正餐智能POS6.0.1.1改版后,点击反结账进入点菜界面后无法进行加菜的FAQ
    关于正餐智能POS6.0.1.1改版后,订单模块无法进行部分退款的FAQ
    退款证书相关
    简易付主副机和打印机配置
    秒点直连操作文档
    智能POS打印配置&常见问题FAQ 12-14 后期持续更新
    ERP主副机和打印机配置FAQ
    ASP.NET没有魔法——ASP.NET MVC Controller的实例化与执行
    ASP.NET没有魔法——ASP.NET MVC 路由的匹配与处理
    ASP.NET没有魔法——ASP.NET MVC路由
  • 原文地址:https://www.cnblogs.com/knife-rose/p/12359860.html
Copyright © 2011-2022 走看看