AC日记——「SCOI2015」情报传递 LiBreOJ 2011

#2011. 「SCOI2015」情报传递

思路:

  可持久化树状数组模板;

代码:

#include <bits/stdc++.h>
using namespace std;
#define maxn 200005
#define maxm maxn*100
int deep[maxn],f[maxn],id[maxn],top[maxn],cnt,soot;
int head[maxn],V[maxn],E[maxn],lar[maxn],size[maxn];
int val[maxm],root[maxn],ch[maxm][2],tot,Tl,Tr,n,m,Ans;
inline void in(int &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();
    }
}
void build(int &now,int l,int r)
{
    now=++tot;
    if(l==r) return;int mid=l+r>>1;
    build(ch[now][0],l,mid);
    build(ch[now][1],mid+1,r);
}
void add(int &now,int pre,int l,int r,int to,int x)
{
    now=++tot,val[now]=val[pre]+x;
    if(l==r) return;int mid=l+r>>1;
    if(to<=mid) add(ch[now][0],ch[pre][0],l,mid,to,x),ch[now][1]=ch[pre][1];
    else add(ch[now][1],ch[pre][1],mid+1,r,to,x),ch[now][0]=ch[pre][0];
}
int lowbit(int x)
{
    return x&(-x);
}
void add(int to1,int to2,int x)
{
    while(to1<=n) add(root[to1],root[to1],1,m,to2,x),to1+=lowbit(to1);
}
void dfs1(int now)
{
    deep[now]=deep[f[now]]+1,size[now]=1;
    for(int i=head[now];i;i=E[i])
    {
        dfs1(V[i]),size[now]+=size[V[i]];
        if(size[lar[now]]<size[V[i]]) lar[now]=V[i];
    }
}
void dfs2(int now,int chain)
{
    top[now]=chain,id[now]=++cnt;
    root[id[now]]=root[0];
    if(lar[now])
    {
        dfs2(lar[now],chain);
        for(int i=head[now];i;i=E[i])
        {
            if(V[i]==lar[now]) continue;
            dfs2(V[i],V[i]);
        }
    }
}
int query(int now,int l,int r)
{
    if(l>=Tl&&r<=Tr) return val[now];
    int mid=l+r>>1,res=0;
    if(Tl<=mid) res+=query(ch[now][0],l,mid);
    if(Tr>mid) res+=query(ch[now][1],mid+1,r);
    return res;
}
int query(int l,int r)
{
    l--;int res=0;
    while(r) res+=query(root[r],1,m),r-=lowbit(r);
    while(l) res-=query(root[l],1,m),l-=lowbit(l);
    return res;
}
int query(int x,int y,int tl,int tr)
{
    int res=0;Tl=tl,Tr=tr;
    while(top[x]!=top[y])
    {
        if(deep[top[x]]<deep[top[y]]) res+=query(id[top[y]],id[y]),y=f[top[y]];
        else res+=query(id[top[x]],id[x]),x=f[top[x]];
    }
    if(deep[x]>deep[y]) swap(x,y);
    res+=query(id[x],id[y]);
    return res;
}
int lca(int x,int y)
{
    while(top[x]!=top[y])
    {
        if(deep[top[x]]>deep[top[y]]) x=f[top[x]];
        else y=f[top[y]];
    }
    return deep[x]<deep[y]?deep[x]:deep[y];
}
int main()
{
    freopen("data.txt","r",stdin);
    freopen("data.out","w",stdout);
    in(n);int op,u,v,c;
    for(int i=1;i<=n;i++)
    {
        in(f[i]);
        if(!f[i]) soot=i;
        else E[i]=head[f[i]],V[i]=i,head[f[i]]=i;
    }
    in(m);
    build(root[0],1,m),dfs1(soot),dfs2(soot,soot);
    for(int i=1;i<=m;i++)
    {
        in(op);
        if(op==2)in(u),add(id[u],i,1);
        else
        {
            in(u),in(v),in(c),Ans=deep[u]+deep[v]-2*lca(u,v)+1;
            printf("%d ",Ans);
            if(i-c-1>=1) printf("%d\n",query(u,v,1,i-c-1));
            else printf("0\n");
        }
    }
    return 0;
}
时间: 2024-12-28 13:09:43

AC日记——「SCOI2015」情报传递 LiBreOJ 2011的相关文章

AC日记——「SCOI2015」国旗计划 LiBreOJ 2007

#2007. 「SCOI2015」国旗计划 思路: 跪烂Claris 代码: #include <cstdio> #include <algorithm> #define maxn 800010 int n,m,ai[maxn][2],bi[maxn],f[maxn<<1],st[maxn]; int g[maxn],nxt[maxn<<1],q[maxn<<1],t,ans[maxn],L,x,y,i; inline void in(int&a

AC日记——「HNOI2017」单旋 LiBreOJ 2018

#2018. 「HNOI2017」单旋 思路: set+线段树: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxtree maxn<<2 int val[maxtree],tag[maxtree],L[maxtree],R[maxtree],mid[maxtree]; int op[maxn],ki[maxn],bi[maxn],cnt,size,n,ch[maxn]

AC日记——「SDOI2017」序列计数 LibreOJ 2002

「SDOI2017」序列计数 思路: 矩阵快速幂: 代码: #include <bits/stdc++.h> using namespace std; #define mod 20170408 #define ll long long struct MatrixType { int n,m; ll ai[105][105]; void mem(int n_,int m_) { n=n_,m=m_; for(int i=0;i<=n;i++) for(int v=0;v<=m;v++

AC日记——「SCOI2016」背单词 LiBreOJ 2012

#2012. 「SCOI2016」背单词 思路: Orz: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 #define maxm 510005 int n,ch[maxm][26],tot=1,len,head[maxm],E[maxm],V[maxm],cnt=1; int val[maxm],cnt2,size[maxm],sta[maxm],top; long long ans,sum; ch

LibreOJ #2006. 「SCOI2015」小凸玩矩阵

二次联通门 : LibreOJ #2006. 「SCOI2015」小凸玩矩阵 /* LibreOJ #2006. 「SCOI2015」小凸玩矩阵 本来以为是道数据结构题 后来想了想发现不可做 就考虑二分dp判断 推方程推不出来 就考虑用网络流判断了 二分出一个数 将小于这个数的位置的点编号 每行的可行点与下一行可行的点连边 后一边最大流判断可选出的数的个数是否符合要求即可 */ #include <cstdio> #include <iostream> #include <q

LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

#2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MN≤M)的矩阵 A AA,要求小凸从其中选出 N NN 个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的 N NN 个数中第 K KK 大的数字的最小值是多少. 输入格式 第一行给出三个整数

LibreOJ #2007. 「SCOI2015」国旗计划

二次联通门 : LibreOJ #2007. 「SCOI2015」国旗计划 --by Claris /* LibreOJ #2007. 「SCOI2015」国旗计划 跪膜Claris... */ #include <cstdio> #include <iostream> #include <algorithm> const int BUF = 12312312; char Buf[BUF], *buf = Buf; inline void read (int &

LibreOJ #2009. 「SCOI2015」小凸玩密室

二次联通门 : LibreOJ #2009. 「SCOI2015」小凸玩密室 /* LibreOJ #2009. 「SCOI2015」小凸玩密室 树形dp 做到这么正常的题突然感觉好不适应.... 考虑转移 f[x][y] 表示从x点转移到y点的代价 则我们需要处理出以x为根的子树的代价 讨论处理一下即可(有没有左儿子,有没有右儿子,或是都有) 但是这样转移是O(N^2)的 所以我们考虑优化 显然有很多转移是不需要的 比如y在x的子树中时就没必要转移 那么考虑优化 设g[x][i]表示走完x的子

—Libre#2009. 「SCOI2015」小凸玩密室

#2009. 「SCOI2015」小凸玩密室 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方相约玩密室逃脱,这个密室是一棵有 n nn 个节点的完全二叉树,每个节点有一个灯泡.点亮所有灯泡即可逃出密室.每个灯泡有个权值 Ai A_iA?i??,每条边也有个权值 bi b_ib?i??. 点亮第 1 11 个灯泡不需要花费,之后每点亮一个新的灯泡 V VV 的花费,等于上一个被点亮的