zoukankan      html  css  js  c++  java
  • 牛客挑战赛34 A~E

    闷声发大财

    A

    O(nmk)dp即可,因为带了1/2的常数+2s所以很稳

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define min(a,b) (a<b?a:b)
    using namespace std;
    
    int a[801];
    int p[801][801];
    long long f[801][801];
    int n,m,i,j,k,l,K,Y;
    
    int main()
    {
    //	freopen("a.in","r",stdin);
    	
    	scanf("%d%d%d%d",&n,&m,&K,&Y);
    	fo(i,1,n)
    	scanf("%d",&a[i]);
    	fo(i,1,n)
    	{
    		fo(j,1,m)
    		{
    			scanf("%d",&p[i][j]);
    			
    			if (j<Y)
    			p[i][j]+=a[i]*j;
    		}
    	}
    	
    	memset(f,127,sizeof(f));
    	f[0][0]=0;
    	
    	fo(i,0,n-1)
    	{
    		fo(j,0,K)
    		if (f[i][j]<800000000000ll)
    		{
    			fd(k,min(K-j,m),0)
    			f[i+1][j+k]=min(f[i+1][j+k],f[i][j]+p[i+1][k]);
    		}
    	}
    	
    	printf("%lld
    ",f[n][K]);
    }
    

    B

    m=2的约瑟夫问题,给出一个人求n=1~n时剩下这个人的方案&最大的n

    约瑟夫的O(n)递推显然过不了,但是随便打表可以发现答案长这样:

    1 1 3 1 3 5 7 1 3 5 7 9 11 13 15 1...

    随便算

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    using namespace std;
    
    //int f[233];
    long long n,m,s,S,ans1,ans2;
    
    int main()
    {
    //	freopen("b.in","r",stdin);
    	
    	scanf("%lld%lld",&n,&m);
    	
    	if (!(m&1))
    	{
    		printf("0 0
    ");
    		return 0;
    	}
    	
    	S=0;s=1;
    	while (n)
    	{
    		if (n>=s)
    		{
    			n-=s;
    			if (m<=s*2-1)
    			++ans1,ans2=S+(m+1)/2;
    		}
    		else
    		{
    			if (m<=n*2-1)
    			++ans1,ans2=S+(m+1)/2;
    			
    			n=0;
    		}
    		
    		S+=s;
    		s=s*2;
    	}
    	
    	printf("%lld %lld
    ",ans1,ans2);
    	return 0;
    	
    //	f[1]=0;
    //	fo(i,2,100)
    //	f[i]=(f[i-1]+2)%i;
    //	
    //	fo(i,1,100)
    //	cout<<f[i]+1<<" ";
    //	if (!f[i])
    //	cout<<f[i-1]+1<<" ";
    }
    

    C

    在普通循环同构的基础上加上了对角互换

    懒得画

    假设有一条直线穿过圆,并且保证直线上方的数<=对应的直线下方的数

    这样解决了对角互换的条件

    然后将圆旋转,可以发现上下两部分同时旋转了

    于是可以把一对对应点看成一个元素,那么变成元素种数为m(m+1)/2,环的大小为n的普通轮换问题

    直接O(n)枚举会挂,所以枚举gcd,再乘上phi(n/gcd)即可

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define mod 19260817
    #define Mod 19260815
    using namespace std;
    
    int f[mod+1];
    int p[1226565];
    int T,i,j,k,l,len,s;
    long long n,m,ans;
    
    void init()
    {
    	int i,j;
    	
    	fo(i,1,mod) f[i]=i;
    	
    	fo(i,2,mod)
    	{
    		if (f[i]==i)
    		{
    			--f[i];
    			p[++len]=i;
    		}
    		
    		fo(j,1,len)
    		if ((long long)i*p[j]<=mod)
    		{
    			if (!(i%p[j]))
    			{
    				f[i*p[j]]=f[i]*p[j];
    				break;
    			}
    			else
    			f[i*p[j]]=f[i]*(p[j]-1);
    		}
    		else
    		break;
    	}
    }
    
    long long qpower(long long a,int b)
    {
    	long long ans=1;
    	
    	while (b)
    	{
    		if (b&1)
    		ans=ans*a%mod;
    		
    		a=a*a%mod;
    		b>>=1;
    	}
    	
    	return ans;
    }
    
    int gcd(int n,int m)
    {
    	int r=n%m;
    	
    	while (r)
    	{
    		n=m;
    		m=r;
    		r=n%m;
    	}
    	
    	return m;
    }
    
    int main()
    {
    //	freopen("c.in","r",stdin);
    	
    	init();
    	
    	scanf("%d",&T);
    	for (;T;--T)
    	{
    		scanf("%lld%lld",&n,&m);
    		m=m*(m+1)/2%mod;
    		
    		s=floor(sqrt(n));
    		
    		ans=0;
    		fo(i,1,s)
    		if (!(n%i))
    		{
    			ans=(ans+qpower(m,i)*f[n/i]%mod)%mod;
    			if (i*i!=n)
    			ans=(ans+qpower(m,n/i)*f[i]%mod)%mod;
    		}
    //		ans=(ans+qpower(m,gcd(n,i)))%mod;
    		ans=ans*qpower(n,Mod)%mod;
    		
    		printf("%lld
    ",ans);
    	}
    }
    

    D

    sb题

    把平面旋转45°再扩大(sqrt{2})倍(即(x,y)-->(x+y,y-x)),变成D*D的矩形操作

    排序+扫描线

    注意边界不能减

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define max(a,b) (a>b?a:b)
    #define min(a,b) (a<b?a:b)
    #define low(x) (x&-(x))
    #define N 200001
    using namespace std;
    
    struct type{
    	int x,y,s;
    } a[200001];
    int tr[4*N+1];
    int tot,n,D,L,i,j,k,l,x,y,sum;
    long long ans;
    
    bool cmp(type a,type b)
    {
    	return a.x<b.x || a.x==b.x && a.s<b.s;
    }
    
    void change(int t,int l,int r,int x,int s)
    {
    	int mid=(l+r)/2;
    	
    	tr[t]+=s;
    	
    	if (l==r)
    	return;
    	
    	if (x<=mid)
    	change(t*2,l,mid,x,s);
    	else
    	change(t*2+1,mid+1,r,x,s);
    }
    
    int find(int t,int l,int r,int x,int y)
    {
    	int mid=(l+r)/2,ans=0;
    	
    	if (x<=l && r<=y)
    	return tr[t];
    	
    	if (x<=mid)
    	ans+=find(t*2,l,mid,x,y);
    	if (mid<y)
    	ans+=find(t*2+1,mid+1,r,x,y);
    	
    	return ans;
    }
    
    int main()
    {
    //	freopen("d.in","r",stdin);
    	
    	scanf("%d%d%d",&n,&D,&L);
    	fo(i,1,n)
    	{
    		scanf("%d%d",&x,&y);
    		
    		j=x;k=y;
    		x=j+k;
    		y=k-j;
    		
    		a[++tot]={x,y,1};
    		a[++tot]={x+D,y,-1};
    	}
    	
    	sort(a+1,a+tot+1,cmp);
    	
    	fo(i,1,tot)
    	{
    		if (a[i].s==1)
    		{
    			ans+=sum-find(1,1,N,max(a[i].y+100001-D+1,1),min(a[i].y+100001+D-1,N));
    			++sum;
    		}
    		
    		change(1,1,N,a[i].y+100001,a[i].s);
    	}
    	
    	printf("%lld
    ",ans);
    }
    

    E

    用总数-没有交点的即可,删除可以看成加了一个-1的矩形

    求出每个询问上下左右的矩形个数,再减去四个角上的

    注意时间也算一维(不用排序),所以需要cdq

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #define fo(a,b,c) for (a=b; a<=c; a++)
    #define fd(a,b,c) for (a=b; a>=c; a--)
    #define low(x) (x&-(x))
    using namespace std;
    
    struct type{
    	int x1,y1,x2,y2,s,id;
    } a[100001],b[100001];
    struct Type{
    	int s,id;
    } c[200001];
    struct type1{
    	int x,s,id;
    } d[100001];
    struct type2{
    	int x,y,s,id,Id;
    } D[100001];
    int tr[200001];
    int ans[200001];
    int n,i,j,k,l,tp,tot,Tot,sum,len;
    
    bool Cmp(Type a,Type b) {return a.s<b.s;}
    bool cmp(type2 a,type2 b) {return a.x<b.x || a.x==b.x && a.id>b.id;}
    
    void change(int t,int s)
    {
    	while (t<=200000)
    	{
    		tr[t]+=s;
    		t+=low(t);
    	}
    }
    
    void clear(int t)
    {
    	while (t<=200000)
    	{
    		tr[t]=0;
    		t+=low(t);
    	}
    }
    
    int find(int t)
    {
    	int ans=0;
    	
    	while (t)
    	{
    		ans+=tr[t];
    		t-=low(t);
    	}
    	
    	return ans;
    }
    
    void work1()
    {
    	int i;
    	
    	fo(i,1,n)
    	if (d[i].s)
    	change(d[i].x,d[i].s);
    	else
    	ans[d[i].id]-=find(d[i].x-1);
    	
    	memset(tr,0,sizeof(tr));
    }
    
    void work2(int l,int r)
    {
    	int i,mid=(l+r)/2;
    	
    	if (l==r) return;
    	
    	work2(l,mid);
    	work2(mid+1,r);
    	
    	sort(D+l,D+r+1,cmp);
    	
    	fo(i,l,r)
    	if (D[i].Id<=mid && D[i].s)
    	change(D[i].y,D[i].s);
    	else
    	if (D[i].Id>mid && !D[i].s)
    	ans[D[i].id]+=find(D[i].y-1);
    	
    	fo(i,l,r)
    	if (D[i].Id<=mid && D[i].s)
    	clear(D[i].y);
    }
    
    int main()
    {
    //	freopen("e.in","r",stdin);
    	
    	scanf("%d",&n);
    	fo(i,1,n)
    	{
    		scanf("%d",&tp);
    		
    		switch (tp)
    		{
    			case 1:{
    				scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
    				
    				++sum;
    				a[i].s=1;
    				b[++tot]=a[i];
    				break;
    			}
    			case 2:{
    				scanf("%d",&j);
    				
    				--sum;
    				a[i]=b[j];
    				a[i].s=-1;
    				break;
    			}
    			case 3:{
    				scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
    				
    				a[i].id=++Tot;
    				ans[Tot]=sum;
    				break;
    			}
    		}
    	}
    	
    //	---
    	
    	len=0;
    	fo(i,1,n)
    	{
    		c[++len]={a[i].x1,i};
    		c[++len]={a[i].x2,-i};
    	}
    	sort(c+1,c+len+1,Cmp);
    	j=0;
    	fo(i,1,len)
    	{
    		j+=i==1 || c[i].s!=c[i-1].s;
    		
    		if (c[i].id>0)
    		a[c[i].id].x1=j;
    		else
    		a[-c[i].id].x2=j;
    	}
    	
    	len=0;
    	fo(i,1,n)
    	{
    		c[++len]={a[i].y1,i};
    		c[++len]={a[i].y2,-i};
    	}
    	sort(c+1,c+len+1,Cmp);
    	j=0;
    	fo(i,1,len)
    	{
    		j+=i==1 || c[i].s!=c[i-1].s;
    		
    		if (c[i].id>0)
    		a[c[i].id].y1=j;
    		else
    		a[-c[i].id].y2=j;
    	}
    	
    //	---
    	
    	fo(i,1,n)
    	if (a[i].s)
    	d[i]={a[i].x2,a[i].s,0};
    	else
    	d[i]={a[i].x1,0,a[i].id};
    	work1();
    	
    	fo(i,1,n)
    	if (a[i].s)
    	d[i]={200001-a[i].x1,a[i].s,0};
    	else
    	d[i]={200001-a[i].x2,0,a[i].id};
    	work1();
    	
    	fo(i,1,n)
    	if (a[i].s)
    	d[i]={a[i].y2,a[i].s,0};
    	else
    	d[i]={a[i].y1,0,a[i].id};
    	work1();
    	
    	fo(i,1,n)
    	if (a[i].s)
    	d[i]={200001-a[i].y1,a[i].s,0};
    	else
    	d[i]={200001-a[i].y2,0,a[i].id};
    	work1();
    	
    //	---
    	
    	fo(i,1,n)
    	if (a[i].s)
    	D[i]={a[i].x2,a[i].y2,a[i].s,0};
    	else
    	D[i]={a[i].x1,a[i].y1,0,a[i].id};
    	fo(i,1,n)
    	D[i].Id=i;
    	work2(1,n);
    	
    	fo(i,1,n)
    	if (a[i].s)
    	D[i]={200001-a[i].x1,200001-a[i].y1,a[i].s,0};
    	else
    	D[i]={200001-a[i].x2,200001-a[i].y2,0,a[i].id};
    	fo(i,1,n)
    	D[i].Id=i;
    	work2(1,n);
    	
    	fo(i,1,n)
    	if (a[i].s)
    	D[i]={a[i].x2,200001-a[i].y1,a[i].s,0};
    	else
    	D[i]={a[i].x1,200001-a[i].y2,0,a[i].id};
    	fo(i,1,n)
    	D[i].Id=i;
    	work2(1,n);
    	
    	fo(i,1,n)
    	if (a[i].s)
    	D[i]={200001-a[i].x1,a[i].y2,a[i].s,0};
    	else
    	D[i]={200001-a[i].x2,a[i].y1,0,a[i].id};
    	fo(i,1,n)
    	D[i].Id=i;
    	work2(1,n);
    	
    //	---
    	
    	fo(i,1,Tot)
    	printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    【Java】_2_Java程序入门第五课
    【算法和数据结构】_3_线性结构_栈
    Windows程序设计_17_鼠标_1
    网络基础知识1:集线器,网桥,交换机
    [hyddd安全性测试笔记2]浅淡静态代码分析工具
    [Ruby小记]初试~
    Arp攻击实战
    [hyddd安全性测试笔记1]URL Encode and URL Decode
    网络嗅探技术浅析
    Session小记
  • 原文地址:https://www.cnblogs.com/gmh77/p/11915562.html
Copyright © 2011-2022 走看看