Loading

noip模拟27

A.牛半仙的妹子图

比较简单的一道,方法很多,可以使用最小生成树等等..
我们发现每个接受度所到达的目的地是一定的,所以我们预处理出每个接受度所到达的种类集合..
所以我们可以选择权值线段树,先\(Spfa\)求出每个点的路径最小值,然后统计到权值线段树上,累计求前缀和即可..
记得离散化..

A_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define p() printf("Pass")
	#define ll long long int
	#define ull unsigned ll
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memset(y,x,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;

const ll N=7e5+50;

ll m,n,ts,ops,opt,hm,type,maxn,root,tot,sum,mod,alls;
ll head[N],c[N],cnt[N],lsh[N],pre[N],ans[N];
bool vis[N];
struct I { ll u,v,w,nxt; } e[N*2];
struct II { ll ls,rs,sum; } tr[N*64];
struct III { ll path,c; } p[N];
inline bool comp(III i,III j) { return i.path==j.path ? i.c<j.c : i.path<j.path ; }
inline void add(ll u,ll v,ll w)
{
	e[++ts].u=u; 
	e[ts].v=v;
	e[ts].w=w;
	e[ts].nxt=head[u];
	head[u]=ts;
}
queue<ll> que;
void bfs()
{
	for(re i=1;i<=n;i++) p[i].path=1e12;
	p[hm].path=1; vis[hm]=1;
	que.push(hm);
	ll u,v,w;
	while(que.size())
	{
		u=que.front(); que.pop();
		for(re i=head[u];i;i=e[i].nxt)
		{
			if(p[e[i].v].path>max(p[u].path,e[i].w))
			{
				p[e[i].v].path=max(p[u].path,e[i].w);
				if(!vis[e[i].v]) que.push(e[i].v);
				vis[e[i].v]=1;
			}
			else continue;
		}
		vis[u]=0;
	}
	for(re i=1;i<=n;i++) 
	{
		lsh[++alls]=p[i].path;
	}
	sort(lsh+1,lsh+1+n);
	alls=unique(lsh+1,lsh+1+n)-lsh-1;
	for(re i=1;i<=n;i++)
	{
		p[i].path=lb(lsh+1,lsh+1+alls,p[i].path)-lsh;
	}
	return ;
}
ll query(ll x,ll l,ll r,ll pos)
{
	if(!x) return 0;
	if(l==r)
	{
		return tr[x].sum;
	}
	ll mid=(l+r)>>1;	
	if(pos<=mid) return query(tr[x].ls,l,mid,pos);
	else return query(tr[x].rs,mid+1,r,pos);
}
void build(ll &x,ll l,ll r)
{
	if(!x) x=++tot;
	if(l==r)
	{
		tr[x].sum=cnt[l];
		return ;
	}
	ll mid=(l+r)>>1;
	build(tr[x].ls,l,mid); build(tr[x].rs,mid+1,r);
}
inline void Work()
{
	sort(p+1,p+1+n,comp);
	Fill(vis,0);
	for(re i=1;i<=n;i++)
	{
		if(!vis[p[i].c]) sum++;
		vis[p[i].c]=1;
		if(p[i].path!=p[i+1].path)
		{
			cnt[p[i].path]=sum;
		}
	}
	maxn=p[n].path;
	for(re i=1;i<=maxn;i++) if(!cnt[i]) cnt[i]=cnt[i-1];
	build(root,1,maxn);
	ll len,temp,le,ri;
	ll temp1,temp2,temp3,temp4,len1,len2;
	ll ans1,ans2;
	ll lst=0;
	for(re i=1;i<=maxn;i++)
	{
		ans[i]=query(root,1,maxn,i);
	}
	lsh[maxn+1]=lsh[maxn]+1;
	for(re i=1;i<=maxn;i++)
	{
		len=lsh[i+1]-lsh[i];
		pre[i]=pre[i-1]+len*ans[i];
	}
	for(re i=1;i<=ops;i++)
	{
		le=read(),ri=read();
		if(type)
		{
			le=le xor lst; le=(le+mod)%mod; le++;
			ri=ri xor lst; ri=(ri+mod)%mod; ri++;
			if(le>ri) swap(le,ri);
		}
		temp1=ub(lsh+1,lsh+1+alls,le)-lsh;
		len=(le-lsh[temp1-1]);
		ans1=ans[temp1-1]*len+pre[temp1-2];
		temp2=ub(lsh+1,lsh+1+alls,ri)-lsh;
		len=(ri-lsh[temp2-1]+1);
		ans2=ans[temp2-1]*len+pre[temp2-2];
		lst=ans2-ans1; write(lst);
	}
	return ;
}
signed main()
{
	n=read(); m=read(); ops=read(); hm=read(); type=read();
	if(type) mod=read();
	for(re i=1;i<=n;i++)
	{
		p[i].c=read();
	}
	ll u,v,w;
	for(re i=1;i<=m;i++)
	{
		u=read(),v=read(),w=read();
		add(u,v,w); add(v,u,w);
	}
	bfs(); Work();
	return 0;
}

B.牛半仙的妹子Tree

我们发现一个点被标记的条件是:
设当前时间为\(t\),被标记的时间为\(t_0\),感染源为\(u\),当前节点为\(v\),那么需要满足\(t-t_0\geq dep_{lca(u,v)}*2-dep_u-dep-v\)..
于是移项得到:\(t+dep_v \geq dep_{lca(u,v)}*2-dep_u+t_0\)
考虑树剖,在线段树上维护右边的值,并与当前节点进行比较.
这里减去了最右边的\(dep_r\),是因为\(r\)\(lca\)..

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define p() printf("Pass")
	#define ll long long int
	#define ull unsigned ll
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memset(y,x,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;

const ll N=1e5+50;

ll n,m,ts,tot;
ll head[N];
ll dfn[N],rk[N],fa[N],son[N],top[N],dep[N],siz[N];
struct I { ll u,v,nxt; } e[N*2];
struct II { ll l,r,minn,lazy,lazy1; } tr[N*64];
inline void add(ll u,ll v)
{
	e[++ts].u=u;
	e[ts].v=v;
	e[ts].nxt=head[u];
	head[u]=ts;
}
void dfs1(ll now,ll dad,ll depth)
{
	dep[now]=depth; fa[now]=dad;
	siz[now]=1;
	for(re i=head[now];i;i=e[i].nxt)
	{
		if(e[i].v==dad) continue;
		dfs1(e[i].v,now,depth+1);
		siz[now]+=siz[e[i].v];
		if(siz[son[now]]<siz[e[i].v])
		{
			son[now]=e[i].v;
		}
	}
	return ;
}
void dfs2(ll now,ll high)
{
	top[now]=high;
	dfn[now]=++tot; rk[tot]=now;
	if(!son[now]) return ;
	dfs2(son[now],high);
	for(re i=head[now];i;i=e[i].nxt)
	{
		if(e[i].v==fa[now] or e[i].v==son[now]) continue;
		dfs2(e[i].v,e[i].v);
	}
	return ;
}
void spread(ll x)
{
	if(tr[x].lazy1)
	{
		tr[x<<1].minn=tr[x<<1|1].minn=1e11; tr[x<<1].lazy1=tr[x<<1|1].lazy1=1;
		tr[x<<1].lazy=0,tr[x<<1|1].lazy=0;
		tr[x].lazy1=0;
	}
	if(tr[x].lazy)
	{
		ll r1=rk[tr[x<<1].r],r2=rk[tr[x<<1|1].r];
		tr[x<<1].minn=min(tr[x<<1].minn,tr[x].lazy-dep[r1]*2);
		tr[x<<1|1].minn=min(tr[x<<1|1].minn,tr[x].lazy-dep[r2]*2);
		if(!tr[x<<1].lazy) tr[x<<1].lazy=tr[x].lazy;
		else tr[x<<1].lazy=min(tr[x<<1].lazy,tr[x].lazy);
		if(!tr[x<<1|1].lazy) tr[x<<1|1].lazy=tr[x].lazy;
		else tr[x<<1|1].lazy=min(tr[x<<1|1].lazy,tr[x].lazy);
		tr[x].lazy=0;
		return ;
	}
}
void pushup(ll x)
{
	tr[x].minn=min(tr[x<<1].minn,tr[x<<1|1].minn);
	return ;
}
void update(ll x,ll ql,ll qr,ll val)
{
	if(ql>qr) return ;
	if(tr[x].l>=ql and tr[x].r<=qr)
	{
		if(val>=1e9)
		{
			tr[x].minn=1e11,tr[x].lazy1=1;
			tr[x].lazy=0;
			return ;
		}
		tr[x].minn=min(tr[x].minn,val-dep[rk[tr[x].r]]*2);
		if(!tr[x].lazy) tr[x].lazy=val;
		else tr[x].lazy=min(tr[x].lazy,val);
		return ;
	}
	spread(x);
	ll mid=(tr[x].l+tr[x].r)>>1;
	if(ql<=mid) update(x<<1,ql,qr,val);
	if(qr>=mid+1) update(x<<1|1,ql,qr,val);
	pushup(x);
	return ;
}
ll query(ll x,ll ql,ll qr)
{
	if(tr[x].l>=ql and tr[x].r<=qr)
	{
		return tr[x].minn;
	}
	spread(x); ll temp=1e11;
	ll mid=(tr[x].l+tr[x].r)>>1;
	if(ql<=mid) temp=min(temp,query(x<<1,ql,qr));
	if(qr>=mid+1) temp=min(temp,query(x<<1|1,ql,qr));
	pushup(x);
	return temp;
}
void CHANGE(ll t,ll x)
{
	t+=dep[x];
	while(top[x]!=1)
	{
		update(1,dfn[top[x]],dfn[x],t);
		x=fa[top[x]];
	}
	update(1,1,dfn[x],t);
	return ;
}
void CLEAR()
{
	update(1,1,n,1e11);
	return ;
}
void QMIN(ll t,ll x)
{
	t-=dep[x];
	ll temp=1e11;
	while(top[x]!=1)
	{
		temp=min(temp,query(1,dfn[top[x]],dfn[x]));
		if(temp<=t) 
		{
			printf("wrxcsd\n");
			return ;
		}
		x=fa[top[x]];
	}
	temp=min(temp,query(1,1,dfn[x]));
	if(temp<=t) 
	{
		printf("wrxcsd\n");
		return ;
	}
	printf("orzFsYo\n");
	return ;
}
void build(ll x,ll l,ll r)
{
	tr[x].l=l; tr[x].r=r;
	if(tr[x].l==tr[x].r) 
	{
		tr[x].minn=1e11;
		return ;
	}
	ll mid=(l+r)>>1;
	build(x<<1,l,mid); build(x<<1|1,mid+1,r);
	pushup(x);
	return ;
}
signed main()
{
	n=read(); m=read();
	ll u,v,w;
	for(re i=1;i<=n-1;i++) 
	{
		u=read(),v=read();
		add(u,v); add(v,u);
	}
	dfs1(1,0,1); dfs2(1,1);
	build(1,1,n);
	ll opt;
	for(ll i=1;i<=m;i++)
	{
		opt=read(); u=read();
		if(opt==1)
		{
			CHANGE(i,u);
		}
		if(opt==2)
		{
			CLEAR();
		}
		if(opt==3)
		{
			QMIN(i,u);
		}
	}
	return 0;
}

C.牛半仙的妹子序列

显然是极长上升子序列,这里安利Yubai的博客,包教包会(不过可能会有套娃,请读者耐心观看)..

C_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define p() printf("Pass")
	#define ll long long int
	#define ull unsigned ll
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memset(y,x,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;

const ll N=2e5+50;
const ll mod=998244353;

ll n;
ll p[N],org[N],f[N];
struct I { ll l,r,lv,maxn,sum; } tr[N*64];

ll nowmax;
ll calc(ll x,ll lmt)
{
	if(tr[x].l==tr[x].r) return tr[x].maxn>lmt ? tr[x].sum : 0 ;
	if(tr[x<<1|1].maxn>lmt) return (tr[x].lv+calc(x<<1|1,lmt))%mod;
	else return calc(x<<1,lmt);
}
void pushup(ll x)
{
	tr[x].sum=(tr[x<<1].sum+tr[x<<1|1].sum)%mod;
	tr[x].maxn=max(tr[x<<1].maxn,tr[x<<1|1].maxn);
	tr[x].lv=calc(x<<1,tr[x<<1|1].maxn);
	return ;
}
void update(ll x,ll pos,ll sum,ll maxn)
{
	if(tr[x].l==tr[x].r)
	{
		tr[x].sum+=sum;
		tr[x].maxn=maxn;
		return ;
	}
	ll mid=(tr[x].l+tr[x].r)>>1;
	if(pos<=mid) update(x<<1,pos,sum,maxn);
	else update(x<<1|1,pos,sum,maxn);
	pushup(x);
	return ;
}
ll query(ll x,ll ql,ll qr)
{
	ll temp=0;
	if(tr[x].l>=ql and tr[x].r<=qr)
	{
		temp=calc(x,nowmax);
		nowmax=max(nowmax,tr[x].maxn);
		return temp;
	}
	ll mid=(tr[x].l+tr[x].r)>>1;
	if(qr>=mid+1) temp=(temp+query(x<<1|1,ql,qr))%mod;
	if(ql<=mid) temp=(temp+query(x<<1,ql,qr))%mod;
	return temp;
}
void build(ll x,ll l,ll r)
{
	tr[x].l=l; tr[x].r=r;
	if(tr[x].l==tr[x].r) return ;
	ll mid=(tr[x].l+tr[x].r)>>1;
	build(x<<1,l,mid); build(x<<1|1,mid+1,r);
	return ;
}
signed main()
{
	n=read();
	for(re i=1;i<=n;i++)
	{
		p[i]=read();
		org[p[i]]=i;
	}
	build(1,1,n);
	for(re i=1;i<=n;i++)
	{	
		nowmax=0;
		f[i]=query(1,1,p[i]-1);
		if(!f[i]) f[i]=1;
		update(1,p[i],f[i],i);
	}
	ll temp=0,ans=0;
	for(re i=n;i>=1;i--)
	{
		if(org[i]>temp)
		{
			temp=max(temp,org[i]);
			ans=(ans+f[org[i]])%mod;
		}
	}
	write(ans%mod);
	return 0;
}
posted @ 2021-08-07 20:57  AaMuXiiiiii  阅读(26)  评论(0)    收藏  举报