Educational Codeforces Round 54 (Rated for Div. 2) D、E

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章