返回顶部

CSP21

总结:两个题的checker我都自己写了一个,MD,耽误太多时间了,\(Linux\)\(checker\)使用要加g++ checker.cpp -o 程序名

image

这题,性质题,首先发现一个树\(n-1\)条边,每次删偶数条边,所以\(n\)必须是奇数,其次我们发现优先删去深度深的点较为优,删完后,我们发现还剩下一些散点散树,再\(dfs\)一遍删掉即可
若先消除根节点,其叶子节点要是无法消除就wa了,所以贪心消除最靠近叶子的节点

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 2e5+5;
int n,p[N],rt,in[N],dep[N],sz[N],id[N];std::vector<int> edge[N];
bool vis[N];
void dfs1(int u)
{
	// cout<<in[u]<<" "<<u<<" "<<sz[u]<<endl;
	for(auto to:edge[u])
	{
		if(to==p[u])continue;
		dfs1(to);
	}
	if(in[u]%2==0)//回溯的时候删除,相当于从优先下往上删
	{
		in[u]=0;
		for(auto to:edge[u])in[to]--;
		cout<<u<<endl;
		vis[u]=1;
	}
}
void dfs2(int u)
{
	// if(!u)return;
	// cout<<u<<endl;
	if(in[u]%2==0&&!vis[u])//第二遍可以从上往下删
	{
		in[u]=0;
		vis[u]=1;
		cout<<u<<endl;
		for(auto to:edge[u])in[to]--;
		// return;
	}
	for(auto to:edge[u])
	{
		if(to==p[u])continue;
		dfs2(to);
	}
}	
int main()
{
	speed();
	// freopen("T1.in","r",stdin);
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n;
	// cout<<n<<endl;
	for(int i=1;i<=n;i++)
	{
		cin>>p[i];
		// cout<<p[i]<<" ";
		if(p[i])edge[p[i]].pb(i),in[p[i]]++,in[i]++,edge[i].pb(p[i]);//连双向边删父亲
		else rt=i;
	}
	// cout<<endl;
	if(n%2==0)
	{
		cout<<"NO"<<endl;
		return 0;
	}
	cout<<"YES"<<endl;
	// dfs(rt);
	// sort(id+1,id+1+n,[&](auto a,auto b){
	// 	return dep[a]>dep[b];
	// });
	dfs1(rt);
	dfs2(rt);
	return 0;
}
/*
10
0 1 1 2 2 3 3 4 4 7
*/

image
建出最短路树,然后优先删深的就行了

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 3e5+5;
struct Id
{
	ll to,w,id;
}pre[N];
vector <Id> edge[N];
vector <int> e[N];
ll n,m,k,dis[N],in[N];bool vis[N];
struct node
{
	ll u,dis;
	bool operator < (const node& A)const
	{
		return dis>A.dis;
	}
};
void dij()
{
	for(int i=1;i<=n;i++)dis[i]=1e12;
	priority_queue <node> q;
	q.push({1,0});dis[1]=0;
	while(q.size())
	{
		int u=q.top().u;q.pop();
		if(vis[u])continue;
		vis[u]=1;
		for(auto [to,w,id]:edge[u])
		{
			if(dis[to]>dis[u]+w)
			{
				dis[to]=dis[u]+w;
				pre[to].to=u;
				pre[to].id=id;
				q.push({to,dis[to]});				
			}
		}
	}
}
int dep[N],mx;
vector <int> t[N];
void dfs(int u)
{
	dep[u]=dep[pre[u].to]+1;
	mx=max(mx,dep[u]);
	if(u!=1)t[dep[u]].pb(pre[u].id);
	for(auto to:e[u])
	{
		// cout<<u<<"->"<<to<<endl;
		dfs(to);
	}
}
void put(int u)
{
	if(u!=1)cout<<pre[u].id<<" ";
	for(auto to:e[u])
	{
		if(!k)break;
		k--;
		put(to);
	}
}
int main()
{
	speed();
	// freopen("T2.in","r",stdin);
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n>>m>>k;ll u,v,w;
	for(int i=1;i<=m;i++)
	{
		cin>>u>>v>>w;
		edge[u].pb({v,w,i});edge[v].pb({u,w,i});
	}
	dij();
	for(int i=2;i<=n;i++)e[pre[i].to].pb(i);
	if(k>=n-1)
	{
		cout<<n-1<<endl;
		for(int i=2;i<=n;i++)cout<<pre[i].id<<" ";
	}else
	{
		dfs(1);
		cout<<k<<endl;
		bool f=0;
		put(1);
	}
	return 0;
}

image

考场暴力,点不水?

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 1e6+6;
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline void write(ll x)
{
	return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
int n,m,Q;
struct OP
{
	int op,l,r;ll w;
}op[N];
struct st
{
	int l,r;ll w,lz;
}st[N<<2];
inline void pu(int rt)
{
	st[rt].w=st[lid].w+st[rid].w;
}
inline void bt(int rt,int l,int r)
{
	st[rt].l=l;st[rt].r=r;
	st[rt].lz=-1;
	if(l==r)
	{
		st[rt].w=0;return;
	}
	int mid=l+r>>1;
	bt(lid,l,mid);bt(rid,mid+1,r);
	pu(rt);
}
inline void pd(int rt)
{
	if(st[rt].lz!=-1)
	{
		int lz=st[rt].lz;st[rt].lz=-1;
		st[lid].lz=lz;st[rid].lz=lz;
		st[lid].w=lz;st[rid].w=lz;
	}
}
inline void update(int rt,int l,int r,int val)
{
	if(l<=st[rt].l&&st[rt].r<=r)
	{
		st[rt].w=val;
		st[rt].lz=val;
		return;
	}
	pd(rt);
	int mid=(st[rt].l+st[rt].r)>>1;
	if(l<=mid)update(lid,l,r,val);
	if(r>mid)update(rid,l,r,val);
	pu(rt);
	return;
}
inline ll query(int rt,int pos)
{
	if(st[rt].l==st[rt].r)
	{
		return st[rt].w;
	}
	pd(rt);
	ll ans=0;
	int mid=(st[rt].l+st[rt].r)>>1;
	if(pos<=mid)ans+=query(lid,pos);
	else if(pos>mid)ans+=query(rid,pos);	
	// pu(rt);
	return ans;
}
struct node
{
	int l,r,id;;
	bool operator < (const node& A)const
	{
		return id<A.id;
	}
};
int sq,B;
inline void solve()
{
	int l,r;
	for(int i=1;i<=Q;i++)
	{
		l=read();r=read();
		vector <int> a(n+1,0);
		ll ans=0;
		for(int j=l;j<=r;j++)
		{
			if(op[j].op==1)swap(a[op[j].l],a[op[j].r]);
			else if(op[j].op==2)
			{
				for(int k=op[j].l;k<=op[j].r;k++)
				{
					a[k]=op[j].w;
				}

			}else 
			{
				ans+=a[op[j].l];
			}
		}

	}
}
inline void solve2()
{
	int l,r;
	bt(1,1,n);
	for(int i=1;i<=Q;i++)
	{
		l=read();r=read();
		update(1,1,n,0);
		// bt(1,1,n);
		ll ans=0;
		for(int j=l;j<=r;j++)
		{
			if(op[j].op==1)
			{
				// swap(a[op[j].l],a[op[j].r]);
				int t1=query(1,op[j].l),t2=query(1,op[j].r);
				update(1,op[j].l,op[j].l,t2);update(1,op[j].r,op[j].r,t1);
			}
			else if(op[j].op==2)
			{
				update(1,op[j].l,op[j].r,op[j].w);
			}else 
			{
				ans+=query(1,op[j].l);
			}
		}
		// cout<<
		ans==0?putchar_unlocked('0'),void(0):write(ans);
		putchar_unlocked('\n');
	}	
}
int main()
{
	// freopen("T3.in","r",stdin);
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	n=read();m=read();Q=read();
	for(int i=1;i<=m;i++)
	{
		op[i].op=read();
		if(op[i].op==1)
		{
			op[i].l=read();op[i].r=read();
			continue;
		}else if(op[i].op==2)
		{
			op[i].l=read();op[i].r=read();op[i].w=read();
		}else op[i].l=read();
	}
	int l,r;
	solve2();
	return 0;
}

正解,线段树,但是维护的是时间戳,我们操作\(3\)只和最近一次修改它有关,我们用线段树维护时间戳(即为操作下标),然后问题变为了区间求\([L,R]\)操作\(3\)的和,用树状数组维护时间戳对应的值

卡着线过
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 1e6+5;
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline void write(ll x)
{
	return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
int n,m,Q;
int id[N];
struct BIT
{
	ll c[N];
	inline int lowbit(int x){return x&-x;}
	inline ll query(int x){if(x<1)return 0;ll ans=0;while(x){ans+=c[x];x-=lowbit(x);}return ans;}
	inline void add(int x,ll val){if(x<1)return;while(x<=m){c[x]+=val;x+=lowbit(x);}}
}T;
struct Tree
{
	int l,r;ll w,lz;
}st[N<<2];
inline void build(int rt,int l,int r)
{
	st[rt].l=l;st[rt].r=r;
	if(l==r)return;
	int mid=l+r>>1;
	build(lid,l,mid);build(rid,mid+1,r);
}
inline void pushdown(int rt)
{
	if(st[rt].lz)
	{
		int lz=st[rt].lz;st[rt].lz=0;st[lid].lz=st[lid].w=st[rid].lz=st[rid].w=lz;
	}
}
inline void update(int rt,int l,int r,int tim)
{
	if(l<=st[rt].l&&st[rt].r<=r)
	{
		st[rt].w=tim;
		st[rt].lz=tim;
		return ;
	}
	int mid=(st[rt].l+st[rt].r)>>1;
	pushdown(rt);
	if(l<=mid)update(lid,l,r,tim);
	if(r>mid)update(rid,l,r,tim);
	st[rt].w=max(st[lid].w,st[rid].w);
}
inline int query(int rt,int l,int r)
{
	if(st[rt].l==st[rt].r)return st[rt].w;
	int mid=st[rt].l+st[rt].r>>1;
	pushdown(rt);int ans=0;
	if(l<=mid)ans+=query(lid,l,r);
	if(r>mid)ans+=query(rid,l,r);
	return ans;
}
int l[N],r[N],val[N];ll ans[N];std::vector<pii> pos[N];
int main()
{
	// freopen("T3.in","r",stdin);
	// freopen("out.out","w",stdout);
	n=read();m=read();Q=read();
	register int op;build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		op=read();id[i]=op;
		if(op==1)
		{
			l[i]=read();r[i]=read();
			int x=query(1,l[i],l[i]),y=query(1,r[i],r[i]);
			update(1,l[i],l[i],y);update(1,r[i],r[i],x);
		}else if(op==2)
		{
			l[i]=read();r[i]=read();val[i]=read();
			update(1,l[i],r[i],i);		
		}else
		{
			l[i]=read();r[i]=query(1,l[i],l[i]);
		}
	}
	register int L,R;
	for(int i=1;i<=Q;i++)
	{
		L=read();R=read();
		pos[R].push_back({L,i});
	}
	for(int i=1;i<=m;i++)
	{
		if(id[i]==3)T.add(r[i],val[r[i]]);
		for(auto [l,j]:pos[i])
		{
			// cout<<l<<endl;
			ans[j]=T.query(i)-T.query(l-1);
		}
	}
	for(int i=1;i<=Q;i++)
	{
		ans[i]==0?putchar_unlocked('0'),void(0):write(ans[i]);
		putchar_unlocked('\n');
	}
	return 0;
}

有一个关于线段树的优化,因为我们是区间赋值,所以只用一个懒惰标记即可

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 1e6+5;
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline void write(ll x)
{
	return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
int n,m,Q;
int id[N];
struct BIT
{
	ll c[N];
	inline int lowbit(int x){return x&-x;}
	inline ll query(int x){if(x<1)return 0;ll ans=0;while(x){ans+=c[x];x-=lowbit(x);}return ans;}
	inline void add(int x,ll val){if(x<1)return;while(x<=m){c[x]+=val;x+=lowbit(x);}}
}T;
struct Tree
{
	int l,r;ll lz;
}st[N<<2];
inline void build(int rt,int l,int r)
{
	st[rt].l=l;st[rt].r=r;
	if(l==r)return;
	int mid=l+r>>1;
	build(lid,l,mid);build(rid,mid+1,r);
}
inline void pushdown(int rt)
{
	if(st[rt].lz)
	{
		int lz=st[rt].lz;st[rt].lz=0;
		st[lid].lz=st[rid].lz=lz;
	}
}
inline void update(int rt,int l,int r,int tim)
{
	if(l<=st[rt].l&&st[rt].r<=r)
	{
		st[rt].lz=tim;
		return ;
	}
	int mid=(st[rt].l+st[rt].r)>>1;
	pushdown(rt);
	if(l<=mid)update(lid,l,r,tim);
	if(r>mid)update(rid,l,r,tim);
}
inline int query(int rt,int l,int r)
{
	if(st[rt].l==st[rt].r)return st[rt].lz;
	if(st[rt].lz)return st[rt].lz;
	int mid=st[rt].l+st[rt].r>>1;
	pushdown(rt);int ans=0;
	if(l<=mid)ans+=query(lid,l,r);
	if(r>mid)ans+=query(rid,l,r);
	return ans;
}
int l[N],r[N],val[N];ll ans[N];std::vector<pii> pos[N];
int main()
{
	// freopen("T3.in","r",stdin);
	// freopen("out.out","w",stdout);
	n=read();m=read();Q=read();
	register int op;build(1,1,n);
	for(int i=1;i<=m;i++)
	{
		op=read();id[i]=op;
		if(op==1)
		{
			l[i]=read();r[i]=read();
			int x=query(1,l[i],l[i]),y=query(1,r[i],r[i]);
			update(1,l[i],l[i],y);update(1,r[i],r[i],x);
		}else if(op==2)
		{
			l[i]=read();r[i]=read();val[i]=read();
			update(1,l[i],r[i],i);		
		}else
		{
			l[i]=read();r[i]=query(1,l[i],l[i]);
		}
	}
	register int L,R;
	for(int i=1;i<=Q;i++)
	{
		L=read();R=read();
		pos[R].push_back({L,i});
	}
	for(int i=1;i<=m;i++)
	{
		if(id[i]==3)T.add(r[i],val[r[i]]);
		for(auto [l,j]:pos[i])
		{
			// cout<<l<<endl;
			ans[j]=T.query(i)-T.query(l-1);
		}
	}
	for(int i=1;i<=Q;i++)
	{
		ans[i]==0?putchar_unlocked('0'),void(0):write(ans[i]);
		putchar_unlocked('\n');
	}
	return 0;
}

image

逆天,\(hash\)记忆化得了\(80\)

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 5e6+5;const ull B=233;
string s[N];
int n,m;ull p[600005],len[N];
vector <ull> hs[N];
unordered_map <int,unordered_map<int,int>> f;
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline void write(int x)
{
	return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
inline void calc(int id,int len)
{
	// cout<<len<<endl;
	hs[id].resize(len+1,0);
	for(int i=1;i<=len;i=-~i)
	{
		hs[id][i]=hs[id][i-1]*B+s[id][i-1]-'a';
		if(!p[i])p[i]=p[i-1]*B;
	}
}
inline ull get(int id,int l,int r)
{
	return hs[id][r]-hs[id][l-1]*p[r-l+1]; 
}
inline int fen(int x,int y)
{
	int r=min(len[x],len[y]);
	for(int i=r;i>=1;i--)
	{
		if(get(y,1,i)==get(x,len[x]-i+1,len[x]))return i;
	}
	return 0;
}
int main()
{
	// freopen("T4.in","r",stdin);
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	n=read();m=read();
	p[0]=1;
	for(int i=1;i<=n;i=-~i)
	{
		cin>>s[i];
		// __builtin_scanf("%s",s[i]);
		// if(i<=2)cout<<s[i]+1<<endl;
		len[i]|=s[i].size();
		calc(i,len[i]);
	}
	int l,r;
	for(int i=1;i<=m;i=-~i)
	{
		l=read();r=read();//l houzhui
		if(f[l][r])
		{
			f[l][r]==-1?putchar_unlocked('0'),void(0):write(f[l][r]);
			putchar_unlocked('\n');
			continue;
		}
		f[l][r]=fen(l,r);
		if(f[l][r]==0)f[l][r]=-1;
		f[l][r]==-1?putchar_unlocked('0'),void(0):write(f[l][r]);
		putchar_unlocked('\n');
	}
	return 0;
}
posted @ 2024-08-15 19:04  wlesq  阅读(11)  评论(0编辑  收藏  举报