A、B、C都是水題,我就不寫題解了。F 2500分的題我有點頂不住,就沒補了
D. Edge Deletion
D題跑出最短路樹bfs選k個點就可以了。
D題我一直在67超時,原因是沒有加一個vis數組,我一直以爲這個數組可加可不加,今天之後我決定我的迪傑斯特拉一定要加這個東東,因爲可能會卡你。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
using namespace std;
typedef long long ll;
const int N=3e5+10;
struct edge
{
int v;
ll w;
int next,id;
}e[2*N];
int head[N];
int n,m,k;
int cnt=0;
struct node
{
int to;
ll w;
bool operator<(const node &o)const
{
//return w>o.w;
return o.w<w;
}
};
void addedge(int u,int v,ll w,int i)
{
++cnt;
e[cnt]={v,w,head[u],i};head[u]=cnt;
++cnt;
e[cnt]={u,w,head[v],i};head[v]=cnt;
}
int id[N];
int fa[N];
ll dis[N];
int vis[N];
void dij()
{
priority_queue<node>que;
que.push({1,0});
memset(dis,0x3f3f3f3f3f3f3f,sizeof(dis));
dis[1]=0;
fa[1]=1;
while(que.size())
{
node now=que.top();que.pop();
int u=now.to;
if(vis[u]) continue;
vis[u]=1;
for(int i=head[now.to];i;i=e[i].next)
{
int v=e[i].v;
if(vis[v]) continue;
ll w=e[i].w;
if(dis[v]>dis[u]+w)
{
fa[v]=u;id[v]=e[i].id;
dis[v]=dis[u]+w;
que.push({v,dis[v]});
}
}
}
}
vector<int>ans,G[N];
void bfs()
{
queue<int>que;
que.push(1);
while(que.size()&&k>0)
{
int u=que.front();que.pop();
for(int v:G[u])
{
que.push(v);
if(k>0) ans.pb(id[v]),k--;
else break;
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
rep(i,1,m)
{
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
addedge(u,v,w,i);
}
if(k==0) {printf("0");return 0;}
dij();
for(int i =2;i<=n;++i)G[fa[i]].pb(i);
bfs();
printf("%d\n",ans.size());
for(int v:ans) printf("%d ",v);
}
E. Vasya and a Tree
這題我怎麼感覺做過?
樹上主席樹套樹上差分即可。
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=3e5+10;
ll sum[maxn*20],ans[maxn];
int ls[maxn*20],rs[maxn*20],cnt=0,n;
struct node
{
int d,x;
node(int a,int b)
{
d=a,x=b;
}
};
vector<node>q[maxn];
vector<int>G[maxn];
void up(int pre,int &o,int l,int r,int k,int v)//以深度爲位置更新?
{
o=++cnt;
ls[o]=ls[pre],rs[o]=rs[pre];
sum[o]=sum[pre]+v;
if(l==r)return;
int m=(l+r)/2;
if(k<=m)up(ls[pre],ls[o],l,m,k,v);
else up(rs[o],rs[o],m+1,r,k,v);
}
ll qu(int o,int l,int r,int k)
{
if(l>=k&&r<=n||!sum[o])return sum[o];//如果已經是零了,沒必要繼續往下了,
int m=(l+r)/2;
ll res=0;
//if(n>m) //肯定成立
if(k<=m)res=qu(ls[o],l,m,k)+sum[rs[o]];//
else res=qu(rs[o],m+1,r,k);
return res;
}
void dfs(int u,int pre,int fa,int dep)
{
int rt=0;
for(int i=0;i<q[u].size();i++)
{
int k=min(n,q[u][i].d+dep);//能達到的最大深度
if(!rt)up(pre,rt,1,n,k,q[u][i].x);
else up(rt,rt,1,n,k,q[u][i].x);
}
if(!rt)rt=pre;
ans[u]=qu(rt,1,n,dep);
for(int i=0;i<G[u].size();i++)
if(G[u][i]!=fa)
dfs(G[u][i],rt,u,dep+1);
}
int main()
{
int u,v,x,op;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
scanf("%d",&op);
while(op--)
{
scanf("%d%d%d",&u,&v,&x);
v=min(v,n);
q[u].push_back(node(v,x));
}
dfs(1,0,0,1);
for(int i=1;i<n;i++)printf("%I64d ",ans[i]);
printf("%I64d\n",ans[n]);
}