AC日记——[SDOI2011]消耗战 洛谷 P2495

[SDOI2011]消耗战

思路;

  建虚树走树形dp;

代码:

#include <bits/stdc++.h>
using namespace std;
#define INF 1e17
#define maxn 250005
#define ll long long
#define maxm (maxn<<1)
struct LandType {
    ll id,key;
    bool operator<(const LandType pos)const
    {
        return key<pos.key;
    }
};
struct LandType ai[maxn];
ll n,head[maxn],E[maxm],V[maxm],W[maxm],cnt;
ll size[maxn],top[maxn],f[maxn],deep[maxn];
ll lar[maxn],m,id[maxn],dis[maxn],li[maxn];
ll ri[maxn],sta[maxn];
bool if_[maxn];
inline void in(ll &now)
{
    char Cget=getchar();now=0;
    while(Cget>‘9‘||Cget<‘0‘)Cget=getchar();
    while(Cget>=‘0‘&&Cget<=‘9‘)
    {
        now=now*10+Cget-‘0‘;
        Cget=getchar();
    }
}
inline void edge_add(ll u,ll v,ll w)
{
    E[++cnt]=head[u],V[cnt]=v,W[cnt]=w,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,W[cnt]=w,head[v]=cnt;
}
inline void edge_add(ll u,ll v)
{
//    printf("%d %d\n",u,v);
    E[++cnt]=head[u],V[cnt]=v,head[u]=cnt;
    E[++cnt]=head[v],V[cnt]=u,head[v]=cnt;
}
void dfs1(ll now,ll fa,ll pi)
{
    deep[now]=deep[fa]+1,f[now]=fa;
    dis[now]=pi,size[now]=1;
    for(ll i=head[now];i;i=E[i])
    {
        if(V[i]==fa) continue;
        dfs1(V[i],now,min(pi,W[i]));
        size[now]+=size[V[i]];
        if(size[V[i]]>size[lar[now]])lar[now]=V[i];
    }
}
void dfs2(ll now,ll chain)
{
    top[now]=chain,id[now]=++cnt,li[now]=cnt;
    if(lar[now])
    {
        dfs2(lar[now],chain);
        for(ll i=head[now];i;i=E[i])
        {
            if(V[i]==f[now]||V[i]==lar[now]) continue;
            dfs2(V[i],V[i]);
        }
    }
    ri[now]=cnt;
}
inline ll find(ll x,ll y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=f[top[x]];
    }
    return deep[x]<deep[y]?x:y;
}
ll dp(ll now,ll fa)
{
    bool flag=false;
    ll pos=0;
    for(ll i=head[now];i;i=E[i])
    {
        if(V[i]==fa) continue;
        pos+=dp(V[i],now),flag=true;
    }
    bool myj=if_[now];head[now]=0;if_[now]=false;
    if(flag&&!myj) return min(pos,dis[now]);
    else return dis[now];
}
int main()
{
    in(n);ll u,v,w,ki;
    for(ll i=1;i<n;i++)in(u),in(v),in(w),edge_add(u,v,w);
    cnt=0,dfs1(1,0,INF),dfs2(1,1),in(m);
    memset(if_,0,sizeof(if_));memset(head,0,sizeof(head));
    while(m--)
    {
        in(ki),cnt=0;
        for(ll i=1;i<=ki;i++) in(ai[i].id),ai[i].key=id[ai[i].id],if_[ai[i].id]=true;
        sort(ai+1,ai+ki+1);ll p=1;sta[p]=1;
        for(ll i=1;i<=ki;i++)
        {
            ll now=ai[i].id,pos=sta[p],pos_=sta[p-1];
            if(id[now]>li[pos]&&id[now]<=ri[pos]) sta[++p]=now;
            else
            {
                if(id[now]>li[pos_]&&id[now]<=ri[pos_])
                {
                    ll lca=find(now,pos);
                    if(pos!=lca) edge_add(pos,lca);
                    p--;
                    if(lca!=pos_) sta[++p]=lca;
                    sta[++p]=now;
                }
                else
                {
                    while((id[now]<li[pos_]||id[now]>ri[pos_])&&p>1)
                    {
                        edge_add(pos_,pos),p--;
                        pos=sta[p],pos_=sta[p-1];
                    }
                    ll lca=find(now,pos);
                    edge_add(lca,pos),p--;
                    if(pos_!=lca) sta[++p]=lca;
                    sta[++p]=now;
                }
            }
        }
        while(p>1)
        edge_add(sta[p],sta[p-1]),p--;
        printf("%lld\n",dp(1,0));
    }
    return 0;
}
时间: 2024-11-08 04:57:54

AC日记——[SDOI2011]消耗战 洛谷 P2495的相关文章

AC日记——[SDOI2011]染色 洛谷 P2486

题目描述 输入输出格式 输入格式: 输出格式: 对于每个询问操作,输出一行答案. 输入输出样例 输入样例#1: 6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q 3 5 C 5 1 2 Q 3 5 输出样例#1: 3 1 2 说明 思路: 树剖+线段树维护区间颜色数量 来,上代码: #include <cstdio> #include <iostream> #include <algorithm> #define m

AC日记——铺地毯 洛谷 P1003(水水水水水~)

题目描述 为了准备一个独特的颁奖典礼,组织者在会场的一片矩形区域(可看做是平面直角坐标系的第一象限)铺上一些矩形地毯.一共有 n 张地毯,编号从 1 到n .现在将这些地毯按照编号从小到大的顺序平行于坐标轴先后铺设,后铺的地毯覆盖在前面已经铺好的地毯之上. 地毯铺设完成后,组织者想知道覆盖地面某个点的最上面的那张地毯的编号.注意:在矩形地毯边界和四个顶点上的点也算被地毯覆盖. 输入输出格式 输入格式: 输入文件名为carpet.in . 输入共n+2 行. 第一行,一个整数n ,表示总共有 n

AC日记——寻找道路 洛谷 P2296

题目描述 在有向图G 中,每条边的长度均为1 ,现给定起点和终点,请你在图中找一条从起点到终点的路径,该路径满足以下条件: 1 .路径上的所有点的出边所指向的点都直接或间接与终点连通. 2 .在满足条件1 的情况下使路径最短. 注意:图G 中可能存在重边和自环,题目保证终点没有出边. 请你输出符合条件的路径的长度. 输入输出格式 输入格式: 输入文件名为road .in. 第一行有两个用一个空格隔开的整数n 和m ,表示图有n 个点和m 条边. 接下来的m 行每行2 个整数x .y ,之间用一个

AC日记——过河卒 洛谷 1002

题目描述 棋盘上A点有一个过河卒,需要走到目标B点.卒行走的规则:可以向下.或者向右.同时在棋盘上C点有一个对方的马,该马所在的点和所有跳跃一步可达的点称为对方马的控制点.因此称之为“马拦过河卒”. 棋盘用坐标表示,A点(0, 0).B点(n, m)(n, m为不超过20的整数),同样马的位置坐标是需要给出的. 现在要求你计算出卒从A点能够到达B点的路径的条数,假设马的位置是固定不动的,并不是卒走一步马走一步. 输入输出格式 输入格式: 一行四个数据,分别表示B点坐标和马的坐标. 输出格式: 一

AC日记——采花 洛谷 P2056

采花 思路: 莫队: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 int bel[maxn]; struct QueryType { int l,r,id; bool operator <(const QueryType pos)const { if(bel[l]==bel[pos.l]) return r<pos.r; else return bel[l]<bel[pos.l];

AC日记——贪婪大陆 洛谷 P2184

贪婪大陆 思路: 树状数组: 跪烂.. 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 int n,m,ltree[maxn],rtree[maxn],tot; inline void in(int &now) { char Cget=getchar();now=0; while(Cget>'9'||Cget<'0')Cget=getchar(); while(Cget>='0

AC日记——挤牛奶 洛谷 P1204

题目描述 三个农民每天清晨5点起床,然后去牛棚给3头牛挤奶.第一个农民在300秒(从5点开始计时)给他的牛挤奶,一直到1000秒.第二个农民在700秒开始,在 1200秒结束.第三个农民在1500秒开始2100秒结束.期间最长的至少有一个农民在挤奶的连续时间为900秒(从300秒到1200秒),而最长的无人挤奶的连续时间(从挤奶开始一直到挤奶结束)为300秒(从1200秒到1500秒). 你的任务是编一个程序,读入一个有N个农民(1 <= N <= 5000)挤N头牛的工作时间列表,计算以下两

AC日记——积木大赛 洛谷 P1969

题目描述 春春幼儿园举办了一年一度的“积木大赛”.今年比赛的内容是搭建一座宽度为n的大厦,大厦可以看成由n块宽度为1的积木组成,第i块积木的最终高度需要是hi. 在搭建开始之前,没有任何积木(可以看成n块高度为 0 的积木).接下来每次操作,小朋友们可以选择一段连续区间[l, r],然后将第第 L 块到第 R 块之间(含第 L 块和第 R 块)所有积木的高度分别增加1. 小 M 是个聪明的小朋友,她很快想出了建造大厦的最佳策略,使得建造所需的操作次数最少.但她不是一个勤于动手的孩子,所以想请你帮

AC日记——[POI2008]BLO-Blockade 洛谷 [POI2008]BLO-Blockade

[POI2008]BLO-Blockade 思路: tarjan: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxm 500005 #define ll long long ll Count[maxn],E[maxm<<1],V[maxm<<1],head[maxn],cnt; ll size[maxm],dfn[maxn],n,m,tot,low[max