多校冲刺 NOIP 20211105 模拟 (23)

考试经过

开始感觉T1不是那么很可做,于是就去看T2,发现左边的CBX已经开始敲键盘了,看来这是有思路了,有点小慌张

然后发现B哥已经开始码T2了,更jb慌了,心想着这是不是两道我不会的签到题。。。。。然后就开始仔细研究T2

然后发现我都不知道快排的原理是啥。。。。于是先照着他给的那个程序打,结果还过了样例。。。只是大样例给T了

然后发现这就是个sb题,瞎搞了一会,半个小时A掉了。然后看T3,又是构造题,我是构造超级弱者,开始瞎手玩

然后手玩出了一个当时认为很对的结论:从小到大排序,然后让答案接近0着选就好了。。。。最扯的是大样例还过了

然后就交了。然后再看T4,发现有44分是白给的,先拿到手了,想了半个小时,没啥进展,就又回去看T1了

越看越有思路。。。。然后设计了一个\(n^3\)的dp,其实我当时都不知道这是坐标dp,并且觉得我当时很天才

发现\(define\ int\ long long\)之后数组开不下,就滚了一维,心想着已经350了,不低了,不低了,就开始罚坐了

结果出来就成了100+100+28+44=272,T3结论假了emmm。。。。还不如打个背包暴力呢。。。。

T1 回文

\(dp_{i,j,k}\)表示距离出发点为\(i\),横坐标为\(j\),与距离终点距离为\(i\),横坐标为\(k\)配对的方案数,

转移的话就瞎转移就行了

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define int long long
using namespace std;
inline int read()
{
	int x=0,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^48);ch=getchar();}
	return x*f;
}
const int mod=993244853;
int f[2][505][505],n,m,goal,nw;
char s[505][505];
vector<pii>v1[1005],v2[1005];
inline void solve(pii x,int le)
{
	for(auto y:v2[le+1])
	{	
		if(s[y.fi][y.se]==s[x.fi+1][x.se]&&(x.fi+1<=y.fi&&x.se<=y.se))
		{
			if(s[y.fi+1][y.se]==s[x.fi][x.se]) (f[nw^1][x.fi+1][y.fi]+=f[nw][x.fi][y.fi+1])%=mod;
			if(s[y.fi][y.se+1]==s[x.fi][x.se]) (f[nw^1][x.fi+1][y.fi]+=f[nw][x.fi][y.fi])%=mod;
		}
		if(s[y.fi][y.se]==s[x.fi][x.se+1]&&(x.fi<=y.fi&&x.se+1<=y.se))
		{
			if(s[y.fi+1][y.se]==s[x.fi][x.se]) (f[nw^1][x.fi][y.fi]+=f[nw][x.fi][y.fi+1])%=mod;
			if(s[y.fi][y.se+1]==s[x.fi][x.se]) (f[nw^1][x.fi][y.fi]+=f[nw][x.fi][y.fi])%=mod;
		}
	}
}
signed main()
{
	freopen("palin.in","r",stdin);
	freopen("palin.out","w",stdout);
	n=read();m=read(); goal=(n+m-1)/2;
	for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
	if(s[1][1]!=s[n][m]){puts("0");return 0;}
	f[nw][1][n]=1;int ans=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			v1[i+j-1].push_back(mp(i,j));
			v2[n-i+(m-j)+1].push_back(mp(i,j));
		}
	}
	if((n+m-1)&1)
	{
		for(int i=1;i<=goal;i++){
			for(auto x:v1[i]) solve(x,i);nw^=1;
			memset(f[nw^1],0,sizeof(f[nw^1]));
		}
		for(auto x:v1[goal+1])ans+=f[nw][x.fi][x.fi];
	}
	else
	{
		for(int i=1;i<goal;i++){
			for(auto x:v1[i]) solve(x,i);nw^=1;
			memset(f[nw^1],0,sizeof(f[nw^1]));
		}
		for(auto x:v1[goal])for(auto y:v2[goal])ans+=f[nw][x.fi][y.fi];
	}
	printf("%lld\n",ans%mod);
}

T2 快速排序

我们发现\(nan\)无论和谁比较都是\(false\)

那么这个排序的实质就是从左到右枚举,这个区间严格小于它的数放到它的前面,单调队列维护即可

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0,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^48);ch=getchar();}
	return x*f;
}
const int maxn=5e5+5;
struct node{
	bool isnan;int shu,id;
	node(){isnan=0;shu=0;id=0;}
	friend bool operator < (node a,node b){
		if(a.isnan||b.isnan) return false;
		return a.shu<b.shu;
	}
}p[maxn],b[maxn];
int n;
char s[15];
struct data{
	int val,id;
	friend bool operator < (data a,data b){
		if(a.val==b.val) return a.id>b.id;
		return a.val>b.val;
	}
};
priority_queue<data>q;
bool bo[maxn];
int que[maxn],top;
signed main()
{
	freopen("qsort.in","r",stdin);
	freopen("qsort.out","w",stdout);
	int t=read();
	while(t--)
	{
		n=read();top=0;
		for(int i=1;i<=n;i++)bo[i]=0,p[i].isnan=0;
		for(int i=1;i<=n;i++)
		{
			p[i].id=i;
			scanf("%s",s+1);
			if(s[1]=='n'){p[i].isnan=1;}
			else
			{
				p[i].isnan=0;p[i].shu=0;
				int l=strlen(s+1);
				for(int j=1;j<=l;j++)
				p[i].shu=p[i].shu*10+(s[j]-'0');
				q.push((data){p[i].shu,i});
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(p[i].isnan){que[++top]=i;bo[i]=1;continue;}
			else if(bo[i]) continue;
			bo[i]=1;
			while(!q.empty()&&q.top().val<p[i].shu)
			{
				if(!bo[q.top().id])
				que[++top]=q.top().id;
				bo[q.top().id]=1;q.pop();
			}
			que[++top]=i;
		}
		while(!q.empty())q.pop();
		for(int i=1;i<=n;i++) 
		{
			if(p[que[i]].isnan)printf("nan ");
			else printf("%d ",p[que[i]].shu);
		}
		puts("");
	}
}

T3 混乱邪恶

高联2试的一个改编题目,所以证明就不讲了(主要是我不会),那么直接排序,两两一组维护差值,贪心将差值干到0

#include<bits/stdc++.h>
using namespace std;
inline int read()
{
	int x=0,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^48);ch=getchar();}
	return x*f;
}
const int maxn=1e6+5;
int n,sum,m;
struct node{
	int id,x,ans;
	friend bool operator <(node a,node b){
		return a.x<b.x;
	}
}p[maxn];
vector<int>vec[maxn];
bool cmp(node a,node b){return a.id<b.id;}
signed main()
{	
	freopen("chaoticevil.in","r",stdin);
	freopen("chaoticevil.out","w",stdout);
	n=read();m=read();puts("NP-Hard solved");
	for(int i=1;i<=n;i++)p[i].x=read(),p[i].id=i;
	sort(p+1,p+1+n);
	for(int i=1+(n&1);i<=n;i+=2)
	{
		sum+=(p[i+1].x-p[i].x);
		p[i].ans=-1;p[i+1].ans=1;
		vec[p[i+1].x-p[i].x].push_back(i);
	}
	if(n&1)sum-=p[1].x,p[1].ans=-1;
	for(int i=m/3;i>=1;i--)
	{
		if(!vec[i].size()||sum<i*2)continue;
		for(auto y:vec[i]) if(sum>=2*i) 
		sum-=2*i,swap(p[y].ans,p[y+1].ans);
	}
	sort(p+1,p+1+n,cmp);
	for(int i=1;i<=n;i++)printf("%d ",p[i].ans);
}

T4 校门外歪脖树上的鸽子

一道sb数据结构题,干了一下午加半个晚上,树剖一下,开两棵线段树维护自己兄弟的标记

线段树就支持区间加和区间求和就好了

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
#define LL long long
using namespace std;
inline int read()
{
	int x=0,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^48);ch=getchar();}
	return x*f;
}
const int maxn=4e5+5;
int n,m,rt,ch[maxn][2],top[maxn],dfn[maxn],siz[maxn],dep[maxn],fa[maxn],son[maxn];
int tp[maxn],le[maxn],dfa[maxn],u1[maxn],u0[maxn],ha[maxn],p1[maxn],p2[maxn],cnt;
map<pii,int>mp;
inline void dfs1(int x,int f)
{
	fa[x]=f;dep[x]=dep[f]+1;siz[x]=le[x]=1;p1[x]=p2[x]=x;
	if(!f)u0[x]=u1[x]=x; else u0[x]=!tp[x]?u0[f]:x,u1[x]=tp[x]?u1[f]:x;
	if(x>n) dfs1(ls(x),x),dfs1(rs(x),x),son[x]=siz[ls(x)]>siz[rs(x)]?ls(x):rs(x),
	siz[x]+=siz[ls(x)]+siz[rs(x)],le[x]=le[ls(x)]+le[rs(x)],p1[x]=p1[ls(x)],p2[x]=p2[rs(x)];
	mp[make_pair(p1[x],p2[x])]=x;
}
inline void dfs2(int x,int tp)
{
	dfn[x]=++cnt;dfa[cnt]=x;top[x]=tp;
	if(x>n) dfs2(son[x],tp);else return;
	if(ls(x)==son[x]) dfs2(rs(x),rs(x));
	else dfs2(ls(x),ls(x));
}
inline int LCA(int x,int y)
{
	while(top[x]!=top[y])
	{if(dep[top[x]]<dep[top[y]]) swap(x,y);x=fa[top[x]];}
	if(dep[x]<dep[y]) return x;return y;
}
inline int pot(int x,int y)
{
	x=top[x];while(x!=top[y])if(fa[x]==y) 
	return x;else x=top[fa[x]];
	return son[y];
}
struct tree{
	#define lid id<<1
	#define rid id<<1|1
	LL sum[maxn<<2],lazy[maxn<<2],val[maxn<<2];
	inline void build(int id,int l,int r,int flag)
	{
		if(l==r){if(tp[dfa[l]]!=flag)val[id]=le[ha[dfa[l]]];return;}
		int mid=(l+r)>>1;build(lid,l,mid,flag);build(rid,mid+1,r,flag);
		val[id]=val[lid]+val[rid];
	}
	inline void pushdown(int id)
	{
		if(!lazy[id]) return;
		sum[lid]+=val[lid]*lazy[id]; lazy[lid]+=lazy[id];
		sum[rid]+=val[rid]*lazy[id]; lazy[rid]+=lazy[id];
		lazy[id]=0;
	}
	inline void update(int id,int l,int r,int ll,int rr,int v)
	{
		if(l>=ll&&r<=rr){sum[id]+=v*val[id];lazy[id]+=v;return ;}
		int mid=(l+r)>>1;pushdown(id);
		if(ll<=mid) update(lid,l,mid,ll,rr,v);
		if(rr>mid) update(rid,mid+1,r,ll,rr,v);
		sum[id]=sum[lid]+sum[rid];
	}
	inline LL query(int id,int l,int r,int ll,int rr)
	{
		if(l>=ll&&r<=rr) return sum[id];
		int mid=(l+r)>>1;pushdown(id);LL ans=0;
		if(ll<=mid) ans+=query(lid,l,mid,ll,rr);
		if(rr>mid) ans+=query(rid,mid+1,r,ll,rr);
		return ans;
	}
	inline void treeup(int x,int y,int d)
	{
		while(top[x]!=top[y]){update(1,1,2*n-1,dfn[top[x]],dfn[x],d);x=fa[top[x]];}
		if(x!=y) update(1,1,2*n-1,dfn[y]+1,dfn[x],d);
	}
	inline LL treeque(int x,int y)
	{
		LL res=0; while(top[x]!=top[y])
		{res+=query(1,1,2*n-1,dfn[top[x]],dfn[x]);x=fa[top[x]];}
		if(x!=y) res+=query(1,1,2*n-1,dfn[y]+1,dfn[x]);
		return res;
	}
}s0,s1;
inline void add(int x,int d)
{
	if(tp[x]) x=ha[x],s0.update(1,1,2*n-1,dfn[x],dfn[x],d);
	else x=ha[x],s1.update(1,1,2*n-1,dfn[x],dfn[x],d); 
}
inline LL getv(int x)
{
	if(tp[x]) return x=ha[x],s0.query(1,1,2*n-1,dfn[x],dfn[x]);
	return x=ha[x],s1.query(1,1,2*n-1,dfn[x],dfn[x]);
}
signed main()
{
	freopen("pigeons.in","r",stdin);
	freopen("pigeons.out","w",stdout);
	memset(tp,-1,sizeof(tp));
	n=read();m=read();
	for(int i=n+1;i<2*n;i++) 
	{
		int x=read(),y=read();
		ch[i][0]=x;ch[i][1]=y;
		tp[x]=0;tp[y]=1;
		ha[x]=y;ha[y]=x;
	}
	for(int i=1;i<2*n;i++) if(tp[i]==-1)rt=i;dfs1(rt,0);dfs2(rt,rt);
	ha[rt]=rt;s0.build(1,1,2*n-1,1);s1.build(1,1,2*n-1,0);
	while(m--)
	{
		int o,x,y,k;
		o=read();x=read();y=read();
		k=mp[make_pair(x,y)];
		if(o==1)
		{
			int v=read();
			if(k) add(k,v);
			else
			{
				int xx=u0[x],yy=u1[y],lca=LCA(x,y);
				if(dep[xx]<=dep[lca]) add(pot(x,lca),v);
				else add(xx,v),s0.treeup(xx,pot(x,lca),v);
				if(dep[yy]<=dep[lca]) add(pot(y,lca),v);
				else add(yy,v),s1.treeup(yy,pot(y,lca),v);
			}
		}
		else
		{
			int lca=LCA(x,y);
			if(k) printf("%lld\n",getv(k));
			else 
			{
				int xx=u0[x],yy=u1[y],lca=LCA(x,y);LL res=0;
				if(dep[xx]<=dep[lca]) res+=getv(pot(x,lca));
				else res+=getv(xx)+s0.treeque(xx,pot(x,lca));
				if(dep[yy]<=dep[lca]) res+=getv(pot(y,lca));
				else res+=getv(yy)+s1.treeque(yy,pot(y,lca));
				printf("%lld\n",res);
			}
		}
	}
}
posted on 2021-11-05 20:11  JYFHYX  阅读(38)  评论(0编辑  收藏  举报