2022NOIPA层联训3 ABCD

T1简单题意转化没有想到,甚至正解考试后都死磕半天硬是绕不过弯;T2DP考场想过但是根本不会预设,连正确的DP式子都没想到;T4构造也是瞎弄一番。还能走多久?每天嚷嚷几句就能真的进步吗?多跑几步就真的可以超越什么吗?到底该怎么做,怎么思考,怎么拼,才能有进步,才是对的?
服输是不可能的,既然有挫败,自然要反思:(1)关于套路的题目,你认真总结了吗?(2)需要灵活思考的东西,平时改题有没有多想多试?(3)改题究竟有没有自己好好想,好好分析样例,一步一步理解题目,写代码,看代码,学暴力,学多解。(4)考试的时候:能不能从暴力思维里跳出,认真分析题目,本质和特性,套路和方法,先想暴力,再从暴力一步步推到正解也许是对的,但是容易陷入各种鸡毛蒜皮的优化,实际上没什么屁用,还是从简化问题,抽离模型的角度思考比较好

T1[数据结构:线段树+题目转化]给出序列A,主角是a1,m个操作,每个给出ki个数,从A中删除ki个,加入给出的数。给出Q次修改,有继承关系,问每次修改之后主角是否会被删除。(n<=1e5)

容易想到ai<a1和ai>a1是唯一有用的表示,把小于用0表示,大于用1表示,问题转化成是否存在某次操作时0的个数<del_cnt。发现0_cnt-del_cnt可以表示出主角是否会在本次被删除,于是想要线段树维护每个操作之后0的个数,如果定义0是<a1,1是>=a1,把a1包含进去,在修改的时候需要考虑后面的是否会被修改到,因为当cnt_0<del_cnt时,把1变成0,不会实际改变下一个序列的0和1的个数,也就是需要修改一段前缀截止cnt_0-del_cnt>=0.可以分块找,散块确定位置,很麻烦。
修改一下定义:0是<a1,1是>a1,维护a1的排名,发现只要一次0<-->1的交换一定会改变一段后缀,所以直接维护不用找位置,排名也许会有负数,但是实际意义就是还要加进来几个才可以合法,后面会正确加回去。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
#define int ll
const int N=1e5+100;
int n,m,Q;
int mi[N<<3],tag[N<<3];
int a[N],A,top[N],cha[N];
vector<int>chg[N];
#define lson (rt<<1)
#define rson (rt<<1|1)
inline void Build(int rt,int l,int r)//区间加减,单点查询
{
	if(l==r)mi[rt]=cha[l];
	else
	{
		int mid=(l+r)>>1;
		Build(lson,l,mid);Build(rson,mid+1,r);
		mi[rt]=min(mi[lson],mi[rson]);
	}
}
inline void Pd(int rt)
{
	if(!tag[rt])return;
	tag[lson]+=tag[rt];
	tag[rson]+=tag[rt];
	mi[lson]+=tag[rt];
	mi[rson]+=tag[rt];
	tag[rt]=0;
}
inline void Insert(int rt,int l,int r,int L,int R,int vl)
{
	if(L>R)return;
	if(L<=l&&r<=R)
	{
		tag[rt]+=vl;
		//chu("from:%lld\n",mi[rt]);
		mi[rt]+=vl;//chu("mi[%d--%d]+=%d  mi:%lld\n",l,r,vl,mi[rt]);
		return;
	}
	int mid=(l+r)>>1;
	Pd(rt);
	if(L<=mid)Insert(lson,l,mid,L,R,vl);
	if(R>mid)Insert(rson,mid+1,r,L,R,vl);
	mi[rt]=min(mi[lson],mi[rson]);
	//chu("mi[%d]=min[%d]:%lld,min[%d]:%lld\n",rt,lson,mi[lson],rson,mi[rson]);
}
// inline int Query(int rt,int l,int r,int L,int R)
// {
// 	if(L<=l&&r<=R)return mi[rt];
// 	Pd(rt);
// 	int mid=(l+r)>>1;
// 	int ans=1e9;
// 	if(L<=mid)ans=Query(lson,l,mid,L,R);
// 	if(R>mid)ans=min(ans,Query(rson,mid+1,r,L,R));
// 	return ans;
// }
signed main()
{
 // freopen("a1.in","r",stdin);
  //freopen("1.out","w",stdout);
	n=re(),m=re(),Q=re();
	_f(i,1,n)a[i]=re();
	A=a[1];
	int minn=0;//维护小于A的个数,大于A的个数
	_f(i,1,n)minn+=(a[i]<A);
	_f(i,1,m)
	{
		top[i]=re();
		cha[i]=minn+1-top[i];//维护A的排名-del
		minn-=top[i];
		_f(j,1,top[i])
		{
			int x=re();
			chg[i].push_back(x);
			minn+=(x<A);
		}
	}
	//_f(i,1,m<<2)mi[i]=1e17;
	//_f(i,1,m)chu("cha[%d]:%d\n",i,cha[i]);
	Build(1,1,m);
//	_f(i,1,m<<2)chu("mi[%d]:%lld\n",i,mi[i]);
//	chu("mi:%d\n",mi[1]);
	_f(i,1,Q)
	{
		int year=re(),pos=re(),val=re();
		//chu("val:%lld chg[%d][%d]:%lld\n",val,year,pos-1,chg[year][pos-1]);
		if(val>A&&chg[year][pos-1]<A)//+1
		{
			//chu("add 0!!!!!!!!!!!!!!%d--%d -1\n",year+1,m);
			Insert(1,1,m,year+1,m,-1);
		}
		else if(val<A&&chg[year][pos-1]>A)
		{
			//chu("add 1%d--%d 1\n",year+1,m);
			Insert(1,1,m,year+1,m,1);
		}
		chg[year][pos-1]=val;
		//chu("query:%d mi[1]:%d\n",i,mi[1]);
		if(mi[1]<=0)
		{
			chu("0\n");
		}
		else chu("1\n");
	//	_f(j,1,5)chu("%lld  ",mi[j]);
	//	chu("\n\n");
	}
    return 0;
}
/*
5 3 3
50 40 30 20 10
4 1 2 3 100
1 4
2 6 7
1 3 300
2 1 400
2 1 5
*/

T2【预设型DP】给出n个数的序列进行染色,如果ai-1和ai+1已经有颜色ai就自动有色。求染色染全方案数。(n<=400)

\(dp[i][j]:代表前i个数已经有色,有j个连续段的方案数,考虑再染色一个位置可以染色那些,因为染色顺序不同方案不同,所以本次染色就算是染了之前的位置的,也是不同方案\)

点击查看代码
//吾必胜
#include<bits/stdc++.h>
using namespace std;
#define _f(i,a,b) for(register int i=a;i<=b;++i)
#define f_(i,a,b) for(register int i=a;i>=b;--i)
#define chu printf
#define ll long long
#define rint register int
#define ull unsigned long long
inline ll re()
{
    ll x=0,h=1;
    char ch=getchar();
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')h=-1;
        ch=getchar();
    }
    while(ch<='9'&&ch>='0')
    {
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*h;
}
//#define int ll
const int N=300+10;
int dp[410][410],mod,n;
inline void upd(int&a,ll b)
{
	a=((ll)a+(ll)b)%mod;
}
int main()
{
  // freopen("1.in","r",stdin);
  // freopen("1.out","w",stdout);
	n=re(),mod=re();
	dp[0][0]=1;
	_f(i,1,n)
	{
		_f(j,1,n)
		{
			upd(dp[i][j],dp[i-1][j-1]*1ll*j);//自己一个段,多开1个,多一个段
			upd(dp[i][j],dp[i-1][j]*2ll*j);//插入(1),多开1个,段不变
			if(i>=2)upd(dp[i][j],dp[i-2][j]*2ll*j);//插入(2),多开2个,段不变
			if(i>=2)upd(dp[i][j],dp[i-2][j+1]*2ll*j);//合并(1),隔着2个,多开2个,段少一个,有2*j种选法
			if(i>=3)upd(dp[i][j],dp[i-3][j+1]*1ll*j);//合并(2),隔着3个,多开3个,段少一个,j种训法
		}
	}
	chu("%d",dp[n][1]);
    return 0;
}
/*
*/

T4[树上构造题目]要求构造一棵树,给出每个编号连续的点集合的连通性。(n<=2000)

对于特殊的情况,只有[l,r]和[i,i]可以联通,可以有固定的特殊构造,(n<=3无解)
对于不特殊的情况,定义好区间【l,r】是[l,r]序号集合联通,如果出现[l,r]包含了[l,x1]、[x1+1,x2]、[x2+1,]...[xk+1,r]的极长好区间,那么可以类似特殊构造,这是区间不相交只包含的情况,注意连边必须要求如果从左往右扫,那么边是连接端点,可以贪心理解,尽量不出现在考虑范围外的连续联通块。
如果出现交,发现不影响答案,忽略就行。具体的,枚举右端点,从小区间到大区间拓展。

点击查看代码

<details>
<summary>点击查看代码</summary>

//吾必胜

include<bits/stdc++.h>

using namespace std;

define _f(i,a,b) for(register int i=a;i<=b;++i)

define f_(i,a,b) for(register int i=a;i>=b;--i)

define chu printf

define ll long long

define rint register int

define ull unsigned long long

inline ll re()
{
ll x=0,h=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch'-')h=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*h;
}
const int N=2020;
char s[N][N];
int n,fa[N];
int main()
{
// freopen("1.in","r",stdin);
// freopen("1.out","w",stdout);
n=re();
_f(i,1,n)scanf("%s",s[i]+i),fa[i]=i;
f(i,1,n)
f
(j,i-1,1)
if(s[j][i]
'1'&&fa[i]>j)
{
chu("%d %d\n",i,j);
if(fa[fa[i]-1]>j)
{
chu("%d %d\n",j,fa[i]-1);
f_(k,fa[fa[i]-1]-1,j+1)if(fa[k]==k)chu("%d %d\n",k,i);
}
_f(k,j,i)fa[k]=fa[j];
}
return 0;
}
/*
12
100100000001
11100000001
1000000000
100000000
10010001
1110000
100000
10000
1001
111
10
1
*/

</details>

posted on 2022-10-05 20:28  HZOI-曹蓉  阅读(16)  评论(0)    收藏  举报