739B - Alyona and a tree倍增+差分
发现cf文本读确实变快了,但是用了快读树剖还是过不了2e5,好像常数大了4?
后来才想起来这是离线的树链改值,差分就行了
跪了的树剖:
#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<stack> #include<set> #include<map> #include<vector> #include<iomanip> #include<bitset> using namespace std; // #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) #define sqr(a) (a)*(a) #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)) ll qp(ll a,ll b,ll mod){ ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t; } struct DOT{ll x;ll y;}; //inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} const int dx[4]={0,0,-1,1}; const int dy[4]={1,-1,0,0}; const int inf=0x3f3f3f3f; const ll Linf=0x3f3f3f3f3f3f3f3f; const ll mod=1e9+7;; namespace fastIO{ #define BUF_SIZE 100000 #define OUT_SIZE 100000 #define ll long long //fread->read bool IOerror=0; inline char nc(){ static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; if (p1==pend){ p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); if (pend==p1){IOerror=1;return -1;} //{printf("IO error!\n");system("pause");for (;;);exit(0);} } return *p1++; } inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} inline void read(int &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(ll &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (sign)x=-x; } inline void read(double &x){ bool sign=0; char ch=nc(); x=0; for (;blank(ch);ch=nc()); if (IOerror)return; if (ch=='-')sign=1,ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; if (ch=='.'){ double tmp=1; ch=nc(); for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); } if (sign)x=-x; } inline void read(char *s){ char ch=nc(); for (;blank(ch);ch=nc()); if (IOerror)return; for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; *s=0; } inline void read(char &c){ for (c=nc();blank(c);c=nc()); if (IOerror){c=-1;return;} } #undef OUT_SIZE #undef BUF_SIZE }; using namespace fastIO; const int maxn=2e5+9; int n; struct EDGE{ int v;int w;int next; }G[maxn<<2]; int head[maxn],tot; inline void addedge(int u,int v,int w){ ++tot;G[tot].v=v;G[tot].next=head[u];G[tot].w=w;head[u]=tot; } int top[maxn]; int pre[maxn]; int dep[maxn]; int num[maxn]; //子树尺寸 int p[maxn]; //v的对应位置 int out[maxn]; //退出时间戳 int fp[maxn]; //访问序列 int son[maxn]; //重儿子 int pos; //计时器 inline void init(){ memset(head,-1,sizeof head);tot=0; memset(son,-1,sizeof son); } inline void dfs1(int u,int fa,int d){ dep[u]=d; pre[u]=fa; num[u]=1; for(int i=head[u];~i;i=G[i].next){ int v=G[i].v; if(v==fa)continue; dfs1(v,u,d+G[i].w); num[u]+=num[v]; if(son[u]==-1||num[v]>num[son[u]])son[u]=v; } } inline void getpos(int u,int sp){ top[u]=sp; p[u]=out[u]=++pos; //cout<<u<<"ww"<<p[u]<<endl; fp[p[u]]=u; if(son[u]==-1)return; getpos(son[u],sp); for(int i=head[u];~i;i=G[i].next){ int v=G[i].v; if(v!=son[u]&&v!=pre[u])getpos(v,v); } out[u]=pos; } int a[maxn]; struct NODE{ int l,r; ll sum; ll add; }ST[maxn<<2]; inline void pushup(int rt){ ST[rt].sum=ST[rt<<1].sum+ST[rt<<1|1].sum; } inline void pushdown(int rt){ if(ST[rt].add){ ST[rt<<1].sum+=ST[rt].add*(ST[rt<<1].r-ST[rt<<1].l+1); ST[rt<<1|1].sum+=ST[rt].add*(ST[rt<<1|1].r-ST[rt<<1|1].l+1); ST[rt<<1].add+=ST[rt].add; ST[rt<<1|1].add+=ST[rt].add; ST[rt].add=0; } } inline void build(int l,int r,int rt){ if(l==r){ST[rt].l=ST[rt].r=l;ST[rt].sum=0;return;} ST[rt].l=l;ST[rt].r=r; int m=l+r>>1; build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt); } inline void update(int a,int b,int c,int l,int r,int rt){ if(a<=l&&b>=r){ ST[rt].sum+=(r-l+1)*c; ST[rt].add+=c; return; } int m=l+r>>1; pushdown(rt); if(a<=m)update(a,b,c,l,m,rt<<1); if(b> m)update(a,b,c,m+1,r,rt<<1|1); pushup(rt); } inline ll query(int x,int l,int r,int rt){ if(l==r){return ST[rt].sum;} int m=l+r>>1; pushdown(rt); if(x<=m)return query(x,l,m,rt<<1); else return query(x,m+1,r,rt<<1|1); } inline void solve(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); update(p[top[u]],p[u],1,1,n,1); u=pre[top[u]]; } if(dep[u]<dep[v])swap(u,v); //cout<<p[u]<<"ww"<<p[v]<<endl; update(p[v],p[u],1,1,n,1); } int fa[maxn][50]; ll falen[maxn][50]; int main(){ //scanf("%d",&n); read(n); init(); for(int i=1;i<=n;i++){ //scanf("%d",&a[i]); read(a[i]); } for(int i=2,x,y;i<=n;i++){ //scanf("%d%d",&x,&y); read(x);read(y); addedge(x,i,y); fa[i][0]=x; falen[i][0]=y; } dfs1(1,1,0); getpos(1,1); build(1,n,1); for(int i=0;i<=32;i++){ fa[1][i]=0; falen[0][i]=Linf; falen[1][i]=Linf; } for(int i=1;i<=32;i++){ for(int j=1;j<=n;j++){ fa[j][i]=fa[fa[j][i-1]][i-1]; if(falen[fa[j][i-1]][i-1]==Linf){ falen[j][i]=Linf;continue; } falen[j][i]=falen[fa[j][i-1]][i-1]+falen[j][i-1]; } } for(int i=2;i<=n;i++){ int now=i; for(int j=32;j>=0;j--){ if(falen[now][j] <= a[i]){ a[i]-=falen[now][j]; now=fa[now][j]; } //cout<<i<<"ww"<<now<<"ww"<<a[i]<<endl; } if(i==now)continue; solve(fa[i][0],now); } for(int i=1;i<=n;i++)printf("%lld ",query(p[i],1,n,1)); }
A了的差分,都用的倍增
#include<bits/stdc++.h> //#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<algorithm> #include<queue> #include<string.h> #include<iostream> #include<math.h> #include<stack> #include<set> #include<map> #include<vector> #include<iomanip> #include<bitset> using namespace std; // #define ll long long #define ull unsigned long long #define pb push_back #define FOR(a) for(int i=1;i<=a;i++) #define sqr(a) (a)*(a) #define dis(a,b) sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)) ll qp(ll a,ll b,ll mod){ ll t=1;while(b){if(b&1)t=t*a%mod;b>>=1;a=a*a%mod;}return t; } struct DOT{ll x;ll y;}; inline void read(int &x){int k=0;char f=1;char c=getchar();for(;!isdigit(c);c=getchar())if(c=='-')f=-1;for(;isdigit(c);c=getchar())k=k*10+c-'0';x=k*f;} const int dx[4]={0,0,-1,1}; const int dy[4]={1,-1,0,0}; const int inf=0x3f3f3f3f; const ll Linf=0x3f3f3f3f3f3f3f3f; const ll mod=1e9+7;; const int maxn=2e5+9; int n; struct EDGE{ int v;int w;int next; }G[maxn<<2]; int head[maxn],tot; inline void addedge(int u,int v,int w){ ++tot;G[tot].v=v;G[tot].next=head[u];G[tot].w=w;head[u]=tot; } /* int top[maxn]; int pre[maxn]; int dep[maxn]; int num[maxn]; //子树尺寸 int p[maxn]; //v的对应位置 int out[maxn]; //退出时间戳 int fp[maxn]; //访问序列 int son[maxn]; //重儿子 int pos; //计时器 */ inline void init(){ memset(head,-1,sizeof head);tot=0; //memset(son,-1,sizeof son); } /* inline void dfs1(int u,int fa,int d){ dep[u]=d; pre[u]=fa; num[u]=1; for(int i=head[u];~i;i=G[i].next){ int v=G[i].v; if(v==fa)continue; dfs1(v,u,d+G[i].w); num[u]+=num[v]; if(son[u]==-1||num[v]>num[son[u]])son[u]=v; } } inline void getpos(int u,int sp){ top[u]=sp; p[u]=out[u]=++pos; fp[p[u]]=u; if(son[u]==-1)return; getpos(son[u],sp); for(int i=head[u];~i;i=G[i].next){ int v=G[i].v; if(v!=son[u]&&v!=pre[u])getpos(v,v); } out[u]=pos; } */ ll add[maxn]; int a[maxn]; /* struct NODE{ int l,r; ll sum; ll add; }ST[maxn<<2]; inline void pushup(int rt){ ST[rt].sum=ST[rt<<1].sum+ST[rt<<1|1].sum; } inline void pushdown(int rt){ if(ST[rt].add){ ST[rt<<1].sum+=ST[rt].add*(ST[rt<<1].r-ST[rt<<1].l+1); ST[rt<<1|1].sum+=ST[rt].add*(ST[rt<<1|1].r-ST[rt<<1|1].l+1); ST[rt<<1].add+=ST[rt].add; ST[rt<<1|1].add+=ST[rt].add; ST[rt].add=0; } } inline void build(int l,int r,int rt){ if(l==r){ST[rt].l=ST[rt].r=l;ST[rt].sum=0;return;} ST[rt].l=l;ST[rt].r=r; int m=l+r>>1; build(l,m,rt<<1);build(m+1,r,rt<<1|1);pushup(rt); } inline void update(int a,int b,int c,int l,int r,int rt){ if(a<=l&&b>=r){ ST[rt].sum+=(r-l+1)*c; ST[rt].add+=c; return; } int m=l+r>>1; pushdown(rt); if(a<=m)update(a,b,c,l,m,rt<<1); if(b> m)update(a,b,c,m+1,r,rt<<1|1); pushup(rt); } inline ll query(int x,int l,int r,int rt){ if(l==r){return ST[rt].sum;} int m=l+r>>1; pushdown(rt); if(x<=m)return query(x,l,m,rt<<1); else return query(x,m+1,r,rt<<1|1); } inline void solve(int u,int v){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); update(p[top[u]],p[u],1,1,n,1); u=pre[top[u]]; } if(dep[u]<dep[v])swap(u,v); //cout<<p[u]<<"ww"<<p[v]<<endl; update(p[v],p[u],1,1,n,1); } */ int fa[maxn][50]; ll falen[maxn][50]; void dfs(int u){ for(int i=head[u];~i;i=G[i].next){ dfs(G[i].v); add[u]+=add[G[i].v]; } } int main(){ //scanf("%d",&n); read(n); init(); for(int i=1;i<=n;i++){ //scanf("%d",&a[i]); read(a[i]); } for(int i=2,x,y;i<=n;i++){ //scanf("%d%d",&x,&y); read(x);read(y); addedge(x,i,y); fa[i][0]=x; falen[i][0]=y; } //dfs1(1,1,0); //getpos(1,1); //build(1,n,1); for(int i=0;i<=32;i++){ fa[1][i]=0; falen[0][i]=Linf; falen[1][i]=Linf; } for(int i=1;i<=32;i++){ for(int j=1;j<=n;j++){ fa[j][i]=fa[fa[j][i-1]][i-1]; if(falen[fa[j][i-1]][i-1]==Linf){ falen[j][i]=Linf;continue; } falen[j][i]=falen[fa[j][i-1]][i-1]+falen[j][i-1]; } } for(int i=2;i<=n;i++){ int now=i; for(int j=32;j>=0;j--){ if(falen[now][j] <= a[i]){ a[i]-=falen[now][j]; now=fa[now][j]; } //cout<<i<<"ww"<<now<<"ww"<<a[i]<<endl; } if(i==now)continue; //solve(fa[i][0],now); add[fa[i][0]]++;add[fa[now][0]]--; } dfs(1); for(int i=1;i<=n;i++)printf("%lld ",add[i]); //for(int i=1;i<=n;i++)printf("%lld ",query(p[i],1,n,1)); }