zoukankan      html  css  js  c++  java
  • 3553: [Shoi2014]三叉神经树(树链剖分)

    这道题特别恶心,首先我们可以发现更改的就是出现连续的一或二,那么就用线段树+树链剖分找到这个范围

    想到是不难想,就是打起来恶心罢了= =

    CODE:

    #include<cstdio>

    #include<iostream>

    #include<cstring>

    #include<algorithm>

    #include<stack>

    using namespace std;

    #define maxn 500100 

    struct edges{

    int to,next;

    }edge[maxn*3];

    int l,next[maxn];

    int addedge(int x,int y) {

    edge[++l]=(edges){y,next[x]};next[x]=l;

    }

    int s[maxn],ch[maxn],fa[maxn*3],ans[maxn*3],q[maxn];

    int bfs() {

    int r=0;

    q[++r]=1;

    int l=0;

    while (l<r) {

    int u=q[++l];s[u]=1;

    for (int i=next[u];i;i=edge[i].next) {

    fa[edge[i].to]=u;q[++r]=edge[i].to;

    }

    }

    for (int i=r;i;i--) {

    s[fa[q[i]]]+=s[q[i]];

    ch[fa[q[i]]]=s[ch[fa[q[i]]]]<s[q[i]]?q[i]:ch[fa[q[i]]];

    ans[fa[q[i]]]+=ans[q[i]]>1?1:0;

    }

    }

    int add[maxn],pos[maxn],pre[maxn];

    int cnt;

    bool b[maxn];

    int heavy(int x,bool y) {

    stack<int > s;

    s.push(1);

    add[pos[++cnt]=1]=cnt;

    pre[1]=1;

    while (!s.empty()) {

    int x=s.top();s.pop();

    if (!b[x]&&ch[x]) {

    s.push(x);

    s.push(ch[x]);

    add[pos[++cnt]=ch[x]]=cnt;

    pre[ch[x]]=pre[x];

    b[x]=1;

    continue;

    }

    for (int i=next[x];i;i=edge[i].next) {

    if (edge[i].to!=ch[x]) {

    s.push(x);

    s.push(edge[i].to);

    add[pos[++cnt]=edge[i].to]=cnt;

    pre[edge[i].to]=edge[i].to;

    next[x]=edge[i].next;

    break;

    }

    }

    }

    return 0;

    }

    struct bo {

    int sz,s,len;

    };

    struct node{

    int l,r,lz;bo b;

    }t[maxn*8];

    #define s(x) t[x].b.s

    #define sz(x) t[x].b.sz

    #define len(x) t[x].b.len

    bo update(bo l,bo r) {

    bo ans;

    ans.sz=l.sz+r.sz;

    ans.s=r.s;

    ans.len=r.len;

    if (l.s==r.s&&r.len==r.sz) ans.len+=l.len;

    return ans;

    }

    #define lc(x) (x<<1)

    #define rc(x) ((x<<1)+1)

    #define mid ((r+l)>>1)

    #define upd(x) t[x].b=update(t[lc(x)].b,t[rc(x)].b)

    void build(int x,int l,int r) {

    t[x].l=l;t[x].r=r;

    sz(x)=r-l+1;

    if (l==r) {s(x)=ans[pos[l]];len(x)=1;return ;}

    build(lc(x),l,mid);build(rc(x),mid+1,r);

    upd(x);

    }

    #define lz(x) t[x].lz

    void pushback(int x) {

    if (t[x].lz==0) return;

    int l=lc(x),r=rc(x);

    lz(l)+=lz(x);lz(r)+=lz(x);

    s(l)+=lz(x);s(r)+=lz(x);

    lz(x)=0;

    }

    bo que(int x,int y) {

    int l=t[x].l,r=t[x].r;

    if (r<=y) return t[x].b;

    pushback(x);

    if (y<=mid) return que(lc(x),y);

    if (y>mid) return update(que(lc(x),y),que(rc(x),y));

    }

    void inc(int x,int x1,int y1,int z) {

    int l=t[x].l,r=t[x].r;

    if (y1<l||x1>r) return ;

    if (x1<=l&&r<=y1) {

    t[x].lz+=z;

    s(x)+=z;

    return ;

    }

    pushback(x);

    inc(lc(x),x1,y1,z);inc(rc(x),x1,y1,z);

    upd(x);

    }

    void gen(int x,int flag) {

    while (x) {

    bo tmp=que(1,add[x]);

    switch (flag) {

    case 0:

    if (tmp.s==2) {

    if (tmp.len>=add[x]-add[pre[x]]+1) {

    inc(1,add[pre[x]],add[x],-1);

    x=fa[pre[x]];

    } else {

    inc(1,add[x]-tmp.len,add[x],-1);

    x=0;

    }

    }else {

    inc(1,add[x],add[x],-1);

    x=0;

    }

    break;

    case 1:

    if (tmp.s==1) {

    if (tmp.len>=add[x]-add[pre[x]]+1) {

    inc(1,add[pre[x]],add[x],1);

    x=fa[pre[x]];

    } else {

    inc(1,add[x]-tmp.len,add[x],1);

    x=0;

    }

    }else {

    inc(1,add[x],add[x],1);

    x=0;

    }

    break;

    }

    }

    return ;

    }

    int main(){

    int n;

    scanf("%d",&n);

    for (int i=1;i<=n;i++) {

    int x1,x2,x3;

    scanf("%d%d%d",&x1,&x2,&x3);

    if (x1<=n) addedge(i,x1);else fa[x1]=i;

    if (x2<=n) addedge(i,x2);else fa[x2]=i;

    if (x3<=n) addedge(i,x3);else fa[x3]=i;

    }

    for (int i=1;i<=2*n+1;i++) {

    scanf("%d",&ans[i+n]);

    ans[fa[i+n]]+=ans[i+n];

    }bfs();

    heavy(1,1);

    build(1,1,n);

    int Q;

    scanf("%d",&Q);  

    while (Q--) {

    int x;

    scanf("%d",&x);

    ans[x]^=1;

    gen(fa[x],ans[x]);

    printf("%d ",que(1,1).s>=2?1:0);

    }

    return 0;

    }


  • 相关阅读:
    Linux显示文件内容常用命令
    Linux文件权限和更改权限
    数据存储及恢复的基本原理
    使用jemter发送HTTPS请求
    运行Jmeter时,出现java.util.prefs.WindowsPreferences <init>异常警告
    Server08AD域安装以及推送
    SVN服务器和客户端搭建
    selenium常见操作
    TestNG 入门教程
    ant+TestNG-xslt生成selenium测试报告
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4348894.html
Copyright © 2011-2022 走看看