1.15考试总结

下午突然来了一次考试,不过还挺简单的,要是没有#define int long long被卡常我就AK了

T1-最短路板子题,跑个dijkstra即可

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,x,y,w,m,s,t,g,p,dis[100003],h[100003],ll[100003],px,vis[100003];
vector<int>l[100003],l1[100003];
struct node
{
	int x,di;
	bool operator <(const node &nx)const
	{
		return nx.di<di;
	}
}pp;
priority_queue<node>q;
signed main()
{
	scanf("%lld%lld%lld%lld%lld%lld",&n,&m,&s,&t,&g,&p);
	for(int i=1;i<=n;i++)
		scanf("%lld%lld",&h[i],&ll[i]);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld%lld",&x,&y,&w);
		l[x].push_back(y),l[y].push_back(x),l1[x].push_back(w),l1[y].push_back(w);
	}
	for(int i=1;i<=n;i++)
		dis[i]=1e9;
	dis[s]=0,pp.x=s,pp.di=0,q.push(pp);
	while(!q.empty())
	{
		pp=q.top(),q.pop(),px=pp.x,vis[px]=1;
		for(int j=0;j<l[px].size();j++)
			if(vis[l[px][j]]==0&&pp.di+l1[px][j]<dis[l[px][j]]&&((pp.di+l1[px][j])*p+h[l[px][j]]<ll[l[px][j]]||l[px][j]==t))
			{
				node txt;
				txt.x=l[px][j],txt.di=pp.di+l1[px][j],dis[txt.x]=txt.di,q.push(txt);
			}						
	}
	if(dis[t]<=g)
		cout<<dis[t];
	else
		cout<<"wtnap wa kotori no oyatsu desu!"<<endl;
	return 0;			
}

T2-分块板子题,分块加二分即可

代码

#include<bits/stdc++.h>
using namespace std;
int n,l,r,c,q,a[1000003],tag[1000003],pos[1000003],m,b[1000003],ll,rr,mid,p,su;
char typ;
void update(int l1)
{
	for(int i=(pos[l1]-1)*m+1;i<=min(n,pos[l1]*m);i++)
		a[i]+=tag[pos[i]],b[i]=a[i];
	sort(b+(pos[l1]-1)*m+1,b+min(n,pos[l1]*m)+1);
	tag[pos[l1]]=0;
}
void add(int l1,int r1,int num)
{
	for(int i=l1;i<=min(r1,pos[l1]*m);i++)
		a[i]+=num;
	update(l1);
	if(pos[l1]!=pos[r1])
	{
		for(int i=(pos[r1]-1)*m+1;i<=r1;i++)
			a[i]+=num;
		update(r1);
	}
	for(int i=pos[l1]+1;i<=pos[r1]-1;i++)
		tag[i]+=num;
}
int ask(int l1,int r1,int num)
{
	int ans=0;
	update(l1),update(r1);
	for(int i=l1;i<=min(r1,pos[l1]*m);i++)
		if(a[i]>=num)
			ans++;
	if(pos[l1]!=pos[r1])
		for(int i=(pos[r1]-1)*m+1;i<=r1;i++)
			if(a[i]>=num)
				ans++;
	for(int i=pos[l1]+1;i<=pos[r1]-1;i++)
	{
		ll=(i-1)*m+1,rr=min(n,i*m),p=rr;
		while(ll<=rr)
		{
			mid=(ll+rr)/2;
			if(b[mid]+tag[pos[mid]]>=num)
				rr=mid-1;
			else
				ll=mid+1;
		}
		ans+=p-rr;
	}
	return ans;
}
int main()
{
	scanf("%d%d",&n,&q);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		b[i]=a[i];
	}
	m=sqrt(n);
	for(int i=1;i<=n;i++)
		pos[i]=(i-1)/m+1;
	su=pos[n];
	for(int i=1;i<=su;i++)
		sort(b+(i-1)*m+1,b+min(n,i*m)+1);
	for(int i=1;i<=q;i++)
	{
		scanf("%s",&typ);
		scanf("%d%d%d",&l,&r,&c);
		if(typ=='A')
			cout<<ask(l,r,c)<<endl;
		else
			add(l,r,c);	  
	}
	return 0;
}

T3-LCA板子题,LCA+前缀和维护一下即可

题目要求的是求一段路径的节点深度的k次方和,显然不能很直接的维护,我们可以发现一点性质,

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,x,y,dep[300003],fat[300003],son[300003],siz[300003],topl[300003],rt,k,ans;
long long mi[300003][55],su[55][300003];
vector<int>l[300003];
const long long mod=998244353;
void dfs1(int x1,int fa)
{
	dep[x1]=dep[fa]+1,siz[x1]=1,fat[x1]=fa;
	int maxx=0;
	for(int j=0;j<l[x1].size();j++)
		if(l[x1][j]!=fa)
		{
			dfs1(l[x1][j],x1);
			siz[x1]+=siz[l[x1][j]];
			if(siz[l[x1][j]]>maxx)
				maxx=siz[l[x1][j]],son[x1]=l[x1][j];
		}
}
void dfs2(int x1,int tp)
{
	topl[x1]=tp;
	if(son[x1])
		dfs2(son[x1],tp);
	for(int j=0;j<l[x1].size();j++)
		if(l[x1][j]!=fat[x1]&&l[x1][j]!=son[x1])
			dfs2(l[x1][j],l[x1][j]);	
}
int ask_root(int x1,int xx)
{
	while(topl[x1]!=topl[xx])
	{
		if(dep[topl[x1]]<dep[topl[xx]])
			swap(x1,xx);
		x1=fat[topl[x1]];
	}
	if(dep[x1]<dep[xx])
		swap(x1,xx);
	return xx;
}
signed main()
{
	scanf("%lld",&n);
	for(int i=1;i<n;i++)
	{
		scanf("%lld%lld",&x,&y);
		l[x].push_back(y),l[y].push_back(x);
	}
	for(long long i=1;i<n;i++)
	{
		mi[i][0]=1;
		for(long long j=1;j<=50;j++)
			mi[i][j]=mi[i][j-1]*i%mod,su[j][i]=(su[j][i-1]+mi[i][j])%mod;
	}
	dep[0]=0;	
	dfs1(1,0);
	dfs2(1,1);
	scanf("%lld",&m);
	for(int i=1;i<=m;i++)
	{
		scanf("%lld%lld%lld",&x,&y,&k);
		rt=ask_root(x,y);
		ans=(su[k][dep[x]-1]-su[k][dep[rt]-1]+su[k][dep[y]-1]-su[k][max(0ll,dep[rt]-2)]+2*mod)%mod;
		cout<<ans<<endl;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/dzice/p/12198333.html