Loading

测试「2020牛客NOIP赛前集训营-提高组(第五场)」

T1

签到题。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e6+5;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n;
lxl ans;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("A.in","r",stdin);
#endif
	read(n);
	for(int i=1;i<=n;++i)
		for(int j=i<<1;j<=n;j+=i)
			ans+=(n-j)/j;
	printf("%lld\n",ans);
	return 0;
}

T2

找到 \(T\)\(S\) 中出现的所有位置计数即可。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e7+5;
const lxl mod=998246353;
const lxl p=233;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,k;
char s[maxn],t[maxn];
lxl hshs[maxn],hsht,P[maxn],ans;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("B.in","r",stdin);
#endif
	read(n),read(k);
	scanf(" %s %s",s+1,t+1);
	P[0]=1;
	for(int i=1;i<=n;++i)
		hshs[i]=(hshs[i-1]*p+s[i])%mod,P[i]=(P[i-1]*p)%mod;
	for(int i=1;i<=k;++i) hsht=(hsht*p+t[i])%mod;
	int las=0;
	for(int i=k;i<=n;++i)
		if((hshs[i]-hshs[i-k]*P[k]%mod+mod)%mod==hsht)
		{
			if(las) ans+=1ll*(las-k+1)*(i-las);
			las=i;
		}
	if(las) ans+=1ll*(las-k+1)*(n-las+1);
	printf("%lld\n",ans);
	return 0;
}

T3

将所有数丢到可持久化Trie上,然后差分求第 \(k\) 大即可。因为这道题字符串长度不一致,所以调了1h+。

然后最后30min发现可以直接预处理出所有数字的字典序,然后主席树维护,花了不到20min就调出来了/fad,赛后发现这才是正解。

\(\text{Code}:\)

可持久化Trie:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define ONLINE_JUDGE
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e5+5;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,q;

namespace Trie
{
	int tot,rt[maxn];
	int ch[maxn<<4][10],siz[maxn<<4],idx[maxn<<4];
	inline void insert(int u,int x,int tmp)
	{
		static int buf[10],top;
		top=0;int d=x;
		while(d) buf[++top]=d%10,d/=10;
		for(int i=top;i>=1;--i)
		{
			int c=buf[i];
			siz[u]=siz[tmp]+1;
			idx[u]=idx[tmp];
			for(int j=0;j<=9;++j) ch[u][j]=ch[tmp][j];
			ch[u][c]=++tot;
			u=ch[u][c];
			tmp=ch[tmp][c];
		}
		siz[u]=siz[tmp]+1;
		for(int j=0;j<=9;++j) ch[u][j]=ch[tmp][j];
		idx[u]=x;
	}
	inline int query(int pl,int pr,int k)
	{
		if(idx[pr]-idx[pl]!=0&&k==1) return idx[pr];
		k-=(idx[pr]-idx[pl]!=0);
		for(int i=0;i<=9;++i)
			if(siz[ch[pr][i]]-siz[ch[pl][i]]<k)
				k-=siz[ch[pr][i]]-siz[ch[pl][i]];
			else return query(ch[pl][i],ch[pr][i],k);
		return -1;
	}
}
using Trie::rt;
using Trie::tot;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("C.in","r",stdin);
	freopen("C.out","w",stdout);
#endif
	read(n),read(q);
	for(int i=1,x;i<=n;++i)
	{
		read(x);
		Trie::insert(rt[i]=++tot,x,rt[i-1]);
	}
	int l,r,k;
	while(q--)
	{
		read(l),read(r),read(k);
		printf("%d\n",Trie::query(rt[l-1],rt[r],k));
	}
	return 0;
}

主席树:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#define ONLINE_JUDGE
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e5+5;

#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[1<<21],*p1=buf,*p2=buf;
template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

int n,q;
int val[maxn],a[maxn];

struct number
{
	int dig[10],len,x;
	number(int x):x(x)
	{
		len=0;
		while(x) dig[++len]=x%10,x/=10;
		for(int i=1;(1<<i)<=len;++i)
			swap(dig[i],dig[len-i+1]);
	}
	number(){}
	inline bool operator < (const number &T)const
	{
		int L=min(len,T.len);
		for(int i=1;i<=L;++i)
			if(dig[i]!=T.dig[i]) return dig[i]<T.dig[i];
		return len<T.len;
	}
}num[maxn];

namespace Segment_Tree
{
	int tot;
	int sum[maxn<<5],ch[maxn<<5][2];
	void modify(int &p,int l,int r,int ps,int tmp)
	{
		p=++tot;
		sum[p]=sum[tmp]+1;
		ch[p][0]=ch[tmp][0];ch[p][1]=ch[tmp][1];
		if(l==r) return;
		int mid=(l+r)>>1;
		if(ps<=mid) modify(ch[p][0],l,mid,ps,ch[tmp][0]);
		else modify(ch[p][1],mid+1,r,ps,ch[tmp][1]);
	}
	int query(int pl,int pr,int l,int r,int k)
	{
		if(l==r) return (sum[pr]-sum[pl]&&k==1)?num[l].x:-1;
		int mid=(l+r)>>1;
		if(sum[ch[pr][0]]-sum[ch[pl][0]]>=k)
			return query(ch[pl][0],ch[pr][0],l,mid,k);
		else return query(ch[pl][1],ch[pr][1],mid+1,r,k-(sum[ch[pr][0]]-sum[ch[pl][0]]));
	}
}
int rt[maxn];

int main()
{
#ifndef ONLINE_JUDGE
	freopen("C.in","r",stdin);
	freopen("baoli.out","w",stdout);
#endif
	read(n),read(q);
	for(int i=1;i<=n;++i)
	{
		read(a[i]);
		num[i]=number(a[i]);
	}
	sort(num+1,num+n+1);
	for(int i=1;i<=n;++i)
		val[num[i].x]=i;
	for(int i=1;i<=n;++i)
		Segment_Tree::modify(rt[i],1,n,val[a[i]],rt[i-1]);
	int l,r,k;
	while(q--)
	{
		read(l),read(r),read(k);
		printf("%d\n",Segment_Tree::query(rt[l-1],rt[r],1,n,k));
	}
	return 0;
}

T4

容易发现这是一个树形结构,每个圆向包含它的最小的圆连边,现在问题就是如何找到这个圆。

用扫描线从左往右扫,用set记录扫描线与圆的交点,按纵坐标排序。每次新加入一个圆时,查找它上面第一个圆弧,若这个圆弧是上半圆弧,那么这个圆弧对应的圆就是这个圆的父亲,否则就是它的兄弟。

建完树求LCA即可。

\(\text{Code}:\)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <set>
#define Rint register int
#define INF 0x3f3f3f3f
using namespace std;
typedef long long lxl;
const int maxn=1e5+5;

template <typename T>
inline void read(T &x)
{
	x=0;T f=1;char ch=getchar();
	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	x*=f;
}

struct edge
{
	int u,v,next;
	edge(int u,int v,int next):u(u),v(v),next(next){}
	edge(){}
}e[maxn];

int head[maxn],ecnt;

inline void add(int u,int v)
{
	e[ecnt]=edge(u,v,head[u]);
	head[u]=ecnt++;
}

int n,q;

namespace Tree
{
	int dep[maxn],fa[maxn],top[maxn],son[maxn],siz[maxn];
	void dfs1(int u)
	{
		dep[u]=dep[fa[u]]+1;
		siz[u]=1;
		for(int i=head[u];~i;i=e[i].next)
		{
			int v=e[i].v;
			dfs1(v);
			siz[u]+=siz[v];
			if(siz[v]>siz[son[u]]) son[u]=v;
		}
	}
	void dfs2(int u,int t)
	{
		top[u]=t;
		if(!son[u]) return;
		dfs2(son[u],t);
		for(int i=head[u];~i;i=e[i].next)
		{
			int v=e[i].v;
			if(v==son[u]) continue;
			dfs2(v,v);
		}
	}
	inline int LCA(int a,int b)
	{
		for(;top[a]!=top[b];dep[top[a]]>dep[top[b]]?a=fa[top[a]]:b=fa[top[b]]);
		return dep[a]<dep[b]?a:b;
	}
}
using Tree::dep;
using Tree::fa;

struct circle
{
	int x,y,r;
	circle(int x,int y,int r):x(x),y(y),r(r){}
	circle(){}
}cir[maxn];

struct Time
{
	int x,id,type;
	Time(int x,int id,int type):x(x),id(id),type(type){}
	Time(){}
	inline bool operator < (const Time &T)const
	{
		return x<T.x;
	}
}t[maxn<<1];
int tcnt;

int now;

struct node
{
	int id,type;
	node(int id,int type):id(id),type(type){}
	node(){}
	inline double calcu()const
	{
		return (double)cir[id].y+
		(double)type*sqrt((double)cir[id].r*cir[id].r-(double)(cir[id].x-now)*(cir[id].x-now));
	}
	inline bool operator < (const node &T)const
	{
		return id==T.id?type<T.type:calcu()<T.calcu();
	}
};

set<node> s;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("D.in","r",stdin);
	freopen("D.out","w",stdout);
#endif
	read(n);
	for(int i=1,x,y,r;i<=n;++i)
	{
		read(x),read(y),read(r);
		cir[i]=circle(x,y,r);
		t[++tcnt]=Time(x-r,i,1);
		t[++tcnt]=Time(x+r,i,-1);
	}
	sort(t+1,t+tcnt+1);
	for(int i=1;i<=tcnt;++i)
	{
		now=t[i].x;
		if(t[i].type==1)
		{
			auto it=s.upper_bound(node(t[i].id,1));
			if(it==s.end()) fa[t[i].id]=n+1;
			else if(it->type==1) fa[t[i].id]=it->id;
			else fa[t[i].id]=fa[it->id];
			s.insert(node(t[i].id,1));
			s.insert(node(t[i].id,-1));
		}
		else
		{
			s.erase(s.find(node(t[i].id,1)));
			s.erase(s.find(node(t[i].id,-1)));
		}
	}
	memset(head,-1,sizeof(head));
	for(int i=1;i<=n;++i)
		add(fa[i],i);
	Tree::dfs1(n+1);
	Tree::dfs2(n+1,n+1);
	read(q);
	int u,v;
	while(q--)
	{
		read(u),read(v);
		int f=Tree::LCA(u,v);
		printf("%d\n",dep[u]+dep[v]-2*dep[f]-(u!=f)-(v!=f));
	}
	return 0;
}
posted @ 2020-10-28 11:21  GoPoux  阅读(136)  评论(0编辑  收藏  举报