牛客小白月赛18 总结

牛客小白月赛18 总结_第1张图片
牛客小白月赛18 总结_第2张图片
T1~T4 都是比较简单的水题了(实现和想的过程都挺简单的)
T7是树状数组

T5平衡树打了 F H Q FHQ FHQ但因为区间加出锅考后A了
T6T9貌似都是数学结论题
T8图论题
T10 w d f wdf wdf???


做题&改题概况:
T1,T3,T4 考场秒切
接着T7在 z y c zyc zyc大佬的指导下想出

之后一直肛T5,敲了无旋Treap,但因为不会区间加饮恨

最后比较颓,T2 w y c wyc wyc大佬讲清题意后切掉

考后秒改T5

T8第二周完成

T6,T9数论题

T6类欧几里得
T9积性函数前缀和

T10 S O S D p SOSDp SOSDp问题完全不会

题解们:T1~T5+T7,如下
T8
T6,T9,T10


S o l u t i o n Solution Solution

T1 Forsaken喜欢数论

描述:
f i f_i fi表示每个数的最小质因子,求其前缀和

n ≤ 3 × 1 0 7 n\leq3\times 10^7 n3×107

题解:
这不是线性筛的 v a l val val数组嘛。。。。

时间复杂度: O ( n ) O(n) O(n)

代码:

#include
using namespace std;
const int N=4e7;
int n,v[N+1],prime[N+1],m;
long long ans;
signed main()
{
    scanf("%d",&n);
    for(register int i=2;i<=n;i++)
    {
        if(!v[i])
        {
            v[i]=i;prime[++m]=i;
        }
        for(register int j=1;j<=m;j++)
        {
            if(prime[j]>v[i]||prime[j]*i>n) break;
            v[i*prime[j]]=prime[j];
        }
        ans+=v[i];
    }
    printf("%lld\n",ans);
}

T2 Forsaken喜欢字符串

描述:
牛客小白月赛18 总结_第3张图片
n ≤ 5 × 1 0 4 , k ≤ 5 , q ≤ 1 0 4 , 1 ≤ x ≤ n , 1 ≤ l e n ≤ n n\leq 5\times 10^4,k\leq 5,q\leq 10^4,1\leq x\leq n,1\leq len\leq n n5×104,k5,q104,1xn,1lenn

题解:
k k k这么小。。。
暴力瞎搞就行了啊,用map维护

时间复杂度: O ( ( n + q ) k 3 l o g k ) O((n+q)k^3logk) O((n+q)k3logk)

代码:
全场第二短兼考试时最短
牛客小白月赛18 总结_第4张图片

#include
#include
#include
using namespace std;int n,k,q,x,len,ans;
map<string,int>m,m2;
string s[50001],ls;
signed main()
{
    cin>>n>>k;
    for(register int i=1;i<=n;i++)
    {
        cin>>s[i];
        for(register int j=0;j<k;j++)
         for(register int l=1;j+l-1<k;l++)
          m[s[i].substr(j,l)]++;
    }
    cin>>q;
    while(q--)
    {
        cin>>x>>len;ans=0;m2.clear();
        for(register int i=0;i<k;i++)
         for(register int j=1;i+j-1<k;j++)
          m2[s[x].substr(i,j)]++;
        for(register int i=0;i+len-1<k;i++) ans+=len*(m[s[x].substr(i,len)]-m2[s[x].substr(i,len)]);
        cout<<ans<<endl;
    }
}

T3 Forsaken给学生分组

描述:
给定 n n n个数,要把他们分成 k k k个非空的组,使得每组的极差和最大

k ≤ n ≤ 1 0 5 k\leq n\leq 10^5 kn105

题解:
显然贪心嘛,每组必然是最大的最小的,然后第二大的第二小的以此类推

注意特判不够分组的情况

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)

代码:

#include
#include
using namespace std;
const int N=1e6;
int a[N],n,k,l,r;
long long ans;
signed main()
{
    scanf("%d%d",&n,&k);
    if(n==k) return putchar(48)&0;
    for(register int i=1;i<=n;i++) scanf("%d",a+i);
    sort(a+1,a+1+n);l=1;r=n;
    while(k&&l<=r&&(r-l+1)>k)
    {
        ans+=a[r]-a[l];
        r--;l++;k--;
    }
    printf("%lld",ans);
}

T4 Forsaken喜欢正方形

描述:
...

题解:
判断四边相等就知道是否是菱形了,由于数据水,这样我就过了。。。

时间复杂度: O ( 4 2 × 4 ! ) = O ( 1 ) O(4^2\times 4!)=O(1) O(42×4!)=O(1)

至于垂直随便判断一下就行了

代码:

#include
#include
#include
#define pd if(check()) return puts("hai xing")&0
using namespace std;
double x[5],y[5];
double dist(int i,int j){return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));}
bool xs(int a,int b,int c,int d)
{
    return dist(a,b)==dist(a,c)&&dist(a,b)==dist(c,d)&&dist(a,b)==dist(b,d);
}
bool check()
{
    int qpl[4]={1,2,3,4};
    do
    {
        if(xs(qpl[0],qpl[1],qpl[2],qpl[3])) return true;
    }while(next_permutation(qpl+1,qpl+5));
    return false;
}
signed main()
{
    for(register int i=1;i<=4;i++) scanf("%lf%lf",x+i,y+i);
    if(check()) return puts("wen")&0;
    for(register int i=1;i<=4;i++)
    {
        x[i]++;pd;x[i]--;
        x[i]--;pd;x[i]++;
        y[i]++;pd;y[i]--;
        y[i]--;pd;y[i]++;
    }
    puts("wo jue de bu xing");
}

T5 Forsaken的数列(考后AC)

描述:
牛客小白月赛18 总结_第5张图片

数据范围: n ≤ 1 0 5 n\leq 10^5 n105

题解:
没有第一条就是一道sb线段树题

加上了就是一道sb平衡树题

这里的平衡树是指可以维护序列的平衡树,可以用 S p l a y Splay Splay或无旋 T r e a p Treap Treap解决

时间复杂度: O ( ( n + q ) l o g n ) O((n+q)logn) O((n+q)logn)

代码:

#include
#include
#include
#include
#include
#define ll long long
#define INF 0x3f3f3f3f
#define ls(p) tree[p].lson
#define rs(p) tree[p].rson
#define tls(p) tree[ls(p)]
#define trs(p) tree[rs(p)]
#define t(p) tree[p]
#define tpi t(++tot)
#define tp t(tot)
#define N 200001
using namespace std;int n,opt,a,b,x,rt,p,m,y,z,v;
typedef long long LL;
struct node{int lson,rson,tag,size,rand;LL sum,val;}tree[(N<<7)+10];
inline LL read()
{
	char c;int d=1;LL f=0;
	while(c=getchar(),!isdigit(c))if(c==45)d=-1;f=(f<<3)+(f<<1)+c-48;
	while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
	return d*f;
}
inline void write(register LL x)
{
	if(x<0)putchar(45),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+48);
	return;
}
inline void change(int x,int v){t(x).val+=v;t(x).tag+=v;t(x).sum+=1ll*t(x).size*v;return;}
inline int new_node(long long v=0)//新建节点
{
	static int tot(0);
	tpi.val=v;tp.sum=v;tp.rand=rand();tp.size=1;
	return tot;
}
inline int copy_node(int p)//复制节点
{
	int ret=new_node();
	t(ret)=t(p);
	return ret;
}
inline void push_up(int p)//上传
{
	t(p).size=tls(p).size+trs(p).size+1;
	t(p).sum=tls(p).sum+trs(p).sum+t(p).val;
	return;
}
inline void push_down(int p)//下传
{
	if(!t(p).tag||!p) return;
	LL dif=t(p).tag;
	if(ls(p)) change(ls(p),dif);
	if(rs(p)) change(rs(p),dif);
	tree[p].tag=0;
	return;
}
inline void split(int p,int k,int &x,int &y)//分裂
{
	if(!p) {x=y=0;return;}
	push_down(p);
	if(tls(p).size<k) {x=copy_node(p);split(rs(x),k-tls(p).size-1,rs(x),y);push_up(x);}
	else {y=copy_node(p);split(ls(y),k,x,ls(y));push_up(y);}
	return;
}
inline int merge(int x,int y)//合并
{
	if(!x||!y) return x|y;
	push_down(x);push_down(y);
	if(t(x).rand<t(y).rand){rs(x)=merge(rs(x),y);push_up(x);return x;}
	else {ls(y)=merge(x,ls(y));push_up(y);return y;}
}
inline void add(int l,int r,int v)
{
	split(rt,b,x,z);split(x,a-1,x,y);
	change(y,v);
	rt=merge(merge(x,y),z);
	return;
}
signed main()
{
	srand(time(0));
	n=read();
	for(register int i=1;i<=n;i++) x=read(),rt=merge(rt,new_node(x));
	m=read();
	while(m--)
	{
		opt=read();
		if(opt==1)
		{
			a=read()-1;
			split(rt,a,x,y);
			rt=merge(merge(x,new_node(0)),y);
			continue;
		}
		if(opt==2)
		{
			a=read();b=read();v=read();
			add(a,b,v);
		}
		if(opt==3)
		{
			a=read();b=read();
			split(rt,b,x,z);split(x,a-1,x,y);
			write(t(y).sum);putchar(10);
			rt=merge(merge(x,y),z);
			continue;
		}
	}
}

T7 Forsaken的三维数点

描述:
牛客小白月赛18 总结_第6张图片
数据范围:
n , k ≤ 2 × 1 0 5 n,k\leq 2\times 10^5 n,k2×105

题解:
显然二分,用树状数组维护可以带走多少点,由于二分的只能是整数,所以所有的距离向上取整即可

时间复杂度: O ( n l o g k ) O(nlogk) O(nlogk)

代码:

#include
#include
#include
#define lb(x) x&-x
using namespace std;int n,op;
long long x,y,z,a[200010],l,r,maxn,mid,ans,c[300010];
inline void add(int x){for(;x<=300000;x+=lb(x)) c[x]++;return;}
inline int get(int x){int s=0;for(;x;x-=lb(x)) s+=c[x];return s;}
signed main()
{
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&op);
        if(op==1)
        {
            scanf("%lld%lld%lld",&x,&y,&z);
            add((int)(sqrt(x*x+y*y+z*z)+0.999999999));
        }
        if(op==2)
        {
            scanf("%lld",&x);
            l=0;r=300000;ans=-1;
            while(l<=r)
            {
                mid=l+r>>1;
                if(get(mid)>=x) r=(ans=mid)-1;
                else l=mid+1;
            }
            printf("%lld\n",ans);
        }
    }
}

我好菜啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊

你可能感兴趣的:(总结,牛客比赛)