2022.9.30测试

一测:230pts

T1:找不到了,其实也很简单,就不写了。

T2:P3999 [SHOI2013]二重镇(蓝)

T3:P3990 [SHOI2013]超级跳马(紫)

T4:P3997 [SHOI2013]扇形面积并(紫)

T2:

六进制状压状态,暴力转移。

fi,j,k 为第 i 个数场上状态为 j,仓库状态为 k 的最高得分数。

转移时分在仓库里和场上,如果仓库里有数要将其移到场上后再放置。

暴力模拟即可。

不要问我为什么没有代码,懂得都懂。

T3:

首先可以想到一个位置状态会从与自己相差不到一行,相差列为奇数的列转移过来,那么很明显对于每一行可以求奇数位置或是偶数位置的前缀和。

fi,j 为跳到第 i 行第 j 列的方案数,gi,j 代表第 i 行第 j 列的 kj(mod1)fi,k,即同行与自己相差奇数列的前缀和。

那么可以写出转移方程。

fi,j=gi1,j1+gi,j1+gi+1,j1

gi,j=gi2,j+fi,j

这样就可以矩阵加速了,初始矩阵从上到下分别为 fk,j(1kn)gk,j(1kn)gk,j1(1kn)

剩下的转移矩阵在对应位置上加 1 即可,对此操作如果有疑问可以多去复习下矩阵快速幂。

复杂度:O(27n3×log(m))

O(8n3×log(m)) 的做法,但我太菜考场上没想出来。

#include<iostream>
#include<cstdio>
using namespace std;
const int mod=30011;
const int N=105;
struct matrix
{
	int x,y,a[155][155];
	void init()
	{
		for(int i=1;i<=x;i++)for(int j=1;j<=y;j++)a[i][j]=0;
	}
};
matrix operator *(matrix fi,matrix se)
{
	matrix th;
	th.x=fi.x,th.y=se.y;
	th.init();
	for(int i=1;i<=fi.x;i++)
	{
		for(int j=1;j<=se.y;j++)
		{
			for(int k=1;k<=fi.y;k++)
			{
				th.a[i][j]+=fi.a[i][k]*se.a[k][j];
				th.a[i][j]%=mod;
			}
		}
	}
	return th;
}
matrix quick_pow(matrix x,int y)
{
	matrix num=x,sum;
	sum.x=sum.y=num.x;
	sum.init();
	for(int i=1;i<=sum.x;i++)sum.a[i][i]=1;
	while(y)
	{
		if(y&1)sum=sum*num;
		num=num*num;
		y>>=1;
	}
	return sum;
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	matrix x,y;
	x.x=x.y=3*n;
	x.init();
	y.x=3*n,y.y=1;
	y.init();
	y.a[1][1]=y.a[1+n][1]=1;
	for(int i=1;i<=n;i++)
	{
		int x1=i+n-1,x2=i+n,x3=i+n+1;
		if(x1>n&&x1<=2*n)x.a[i+n][x1]=x.a[i][x1]=1;
		if(x2>n&&x2<=2*n)x.a[i+n][x2]=x.a[i][x2]=1;
		if(x3>n&&x3<=2*n)x.a[i+n][x3]=x.a[i][x3]=1;
	}
	for(int i=n+1;i<=2*n;i++)x.a[i][i+n]=1;
	for(int i=2*n+1;i<=3*n;i++)x.a[i][i-n]=1;
	x=quick_pow(x,m-1);
	y=x*y;
	printf("%d",y.a[n][1]);
	return 0;
}

T4:

扫描线学的有点烂,还是 Splay 耗用。

理解题意后可以把题目看成一个覆盖线段的问题。

对于点在 m 上,看成在 m 上。

对于 l<r,不用处理。

对于 l>r,将问题看成 (l,m)(m+1.r) 两个区间。

对于正常处理点的问题,Splay 可以在 l 时加入这个点,r+1 时删除这个点。

但本题为线段覆盖,所以我们可以把线段的下标看为点的下标,但是一个 (l,r) 的区间只能覆盖 (rl) 的线段数,所以在 r 时就删除这个点即可。

剩下的都是 Splay 板子了,离线排序,插入,删除,在一个点时判断是否树中有超过 k 的节点,如果有,那么搜索第 k 大的数,否则赋为 0

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

#include<iostream>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
const int N=1e5+5;
const int M=1e6+5;
int n,m,k,cnt,root,nl,nr;
struct node2
{
	int name,data;
	bool flag;
}ask[4*N];
int cmp2(node2 fi,node2 se)
{
	if(fi.name==se.name)return fi.flag<se.flag;
	return fi.name<se.name;
}
void clac(int &x,int &y)
{
	nl=0;
	if(x>y)
	{
		nl=x;
		x=-m+1;
	}
}
struct node
{
	int fa,ch[2],siz,cnt,val;
}t[4*N];
inline void newnode(int &x,int fa,int val)
{
	x=++cnt;
	t[x].fa=fa;
	t[x].val=val;
	t[x].cnt=t[x].siz=1;
}
inline void connect(int x,int fa,int son)
{
	t[x].fa=fa;
	t[fa].ch[son]=x;
}
inline bool ident(int x,int fa)
{
	return t[fa].ch[1]==x;
}
inline void pushup(int x)
{
	t[x].siz=t[x].cnt+t[t[x].ch[0]].siz+t[t[x].ch[1]].siz;
}
inline void rotate(int x)
{
	int fa=t[x].fa,ff=t[fa].fa,k=ident(x,fa);
	connect(t[x].ch[k^1],fa,k);
	connect(fa,x,k^1);
	connect(x,ff,ident(fa,ff));
	pushup(fa),pushup(x);
}
void splay(int x,int topp=0)
{
	if(topp==0)root=x;
	while(t[x].fa!=topp)
	{
		int fa=t[x].fa,ff=t[fa].fa;
		if(ff!=topp)ident(x,fa)^ident(fa,ff)?rotate(x):rotate(fa);
		rotate(x);
	}
}
void ins(int val,int &x=root,int fa=0)
{
	if(!x)newnode(x,fa,val),splay(x);
	else if(t[x].val>val)ins(val,t[x].ch[0],x);
	else if(t[x].val<val)ins(val,t[x].ch[1],x);
	else t[x].cnt++,splay(x);
}
void erase(int val,int x=root)
{
	if(t[x].val==val)
	{
		splay(x);
		if(t[x].cnt>=2)t[x].cnt--;
		else if(t[x].ch[1])
		{
			int p=t[x].ch[1];
			while(t[p].ch[0])p=t[p].ch[0];
			splay(p,x);	
			root=p,connect(t[x].ch[0],p,0),t[p].fa=0;
			pushup(p);
		}
		else root=t[x].ch[0],t[t[x].ch[0]].fa=0;
	}
	else if(t[x].val>val)erase(val,t[x].ch[0]);
	else erase(val,t[x].ch[1]);
}
int getrank(int k,int x=root)
{
	if(k<=0)
	{
		splay(x);
		return t[x].val;
	}
	if(k<=t[t[x].ch[0]].siz)return getrank(k,t[x].ch[0]);
	int tmp=k-t[t[x].ch[0]].siz-t[x].cnt;
	if(tmp<=0)
	{
		splay(x);
		return t[x].val;
	}
	return getrank(tmp,t[x].ch[1]);
}
signed main()
{
	//freopen("a.out","r",stdin);
	//freopen("area.out","w",stdout);
	scanf("%lld%lld%lld",&n,&m,&k);
	int cnp=0;
	for(int i=1;i<=n;i++)
	{
		int dat,lc,rc;
		scanf("%lld%lld%lld",&dat,&lc,&rc);
		if(lc==-m)lc=m;
		if(rc==-m)rc=m;
		clac(lc,rc);
		ask[++cnp]=(node2){lc,dat,0};
		ask[++cnp]=(node2){rc,dat,1};
		if(nl)ask[++cnp]=(node2){nl,dat,0};
	}
	sort(ask+1,ask+1+cnp,cmp2);
	int bef=1,num=0,ans=0;
	for(int i=-m+1;i<=m;i++)
	{
		for(;bef<=cnp;bef++)
		{
			if(ask[bef].name!=i)break;
			if(ask[bef].flag==1)num--,erase(ask[bef].data*ask[bef].data);
			else num++,ins(ask[bef].data*ask[bef].data);
		}
		if(num>=k)ans+=getrank(num-k+1);
	}
	printf("%lld",ans);
	return 0;
}
/*
10 100 2
24660 98 32
906 -15 -49
26067 -52 -23
15409 -76 -25
22490 41 65
2600 -10 -7
4310 15 75
20389 -100 -3
4421 8 -40
8664 -70 -95
*/
posted @   Gmt丶Fu9ture  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示