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;
}