邪恶线段树求调玄关

P2572 [SCOI2010] 序列操作

luxiaomao @ 2024-09-05 21:58:45

rt,目前是 10 pts,过了 #7 和 Hack。

马蜂应该还可以,其中懒标记这么写:

  • -1,不用下传
  • 0,覆盖为 0
  • 1,覆盖为 1
  • 2,进行反转

求 dalao 帮条,如果调不出来 Hack 数据也可以,拜谢!!!

#include<bits/stdc++.h>
#define N 100005
using namespace std;

int n,m,a[N];

struct node{int l,r,s,sum[2],lmax[2],rmax[2],ans[2],add;}t[4*N];
void upd(int u)
{
    for(int k = 0;k <= 1;k++)
    {
        t[u].sum[k] = t[2*u].sum[k] + t[2*u+1].sum[k];
        if(t[2*u].sum[k] == t[2*u].s)
            t[u].lmax[k] = max(t[2*u].lmax[k],t[2*u].s+t[2*u+1].lmax[k]);
        else
            t[u].lmax[k] = t[2*u].lmax[k];
        if(t[2*u+1].sum[k] == t[2*u+1].s)
            t[u].rmax[k] = max(t[2*u+1].rmax[k],t[2*u+1].s+t[2*u].rmax[k]);
        else 
            t[u].rmax[k] = t[2*u+1].rmax[k];
        t[u].ans[k] = max(max(t[2*u].ans[k],t[2*u+1].ans[k]),t[2*u].rmax[k]+t[2*u+1].lmax[k]);
    }
}
void build(int u,int l,int r)
{
    t[u].l = l,t[u].r = r,t[u].s = r-l+1,t[u].add = -1;
    if(l == r)
    {
        t[u].sum[a[l]] = 1;
        t[u].lmax[a[l]] = 1;
        t[u].rmax[a[l]] = 1;
        t[u].ans[a[l]] = 1;
        return;
    }
    int mid = l+r>>1;
    build(2*u,l,mid);
    build(2*u+1,mid+1,r);
    upd(u);
}
void pushdown(int u)
{
    if(t[u].add == -1)return;
    if(t[u].add == 2)
    {
        t[2*u].add = 1-t[2*u].add;
        t[2*u+1].add = 1-t[2*u+1].add;
        swap(t[2*u].sum[0],t[2*u].sum[1]);
        swap(t[2*u+1].sum[0],t[2*u+1].sum[1]);
        swap(t[2*u].lmax[0],t[2*u].lmax[1]);
        swap(t[2*u+1].lmax[0],t[2*u+1].lmax[1]);
        swap(t[2*u].rmax[0],t[2*u].rmax[1]);
        swap(t[2*u+1].rmax[0],t[2*u+1].rmax[1]);
        swap(t[2*u].ans[0],t[2*u].ans[1]);
        swap(t[2*u+1].ans[0],t[2*u+1].ans[1]);
    }
    else
    {
        int k = t[u].add;
        t[2*u].add = k;
        t[2*u+1].add = k;
        t[2*u].sum[k] = t[2*u].s,t[2*u].sum[1-k] = 0;
        t[2*u+1].sum[k] = t[2*u+1].s,t[2*u+1].sum[1-k] = 0;
        t[2*u].lmax[k] = t[2*u].s,t[2*u].lmax[1-k] = 0;
        t[2*u+1].lmax[k] = t[2*u+1].s,t[2*u+1].lmax[1-k] = 0;
        t[2*u].rmax[k] = t[2*u].s,t[2*u].rmax[1-k] = 0;
        t[2*u+1].rmax[k] = t[2*u+1].s,t[2*u+1].rmax[1-k] = 0;
        t[2*u].ans[k] = t[2*u].s,t[2*u].ans[1-k] = 0;
        t[2*u+1].ans[k] = t[2*u+1].s,t[2*u+1].ans[1-k] = 0;
    }
    t[u].add = -1;
}
void cov(int u,int l,int r,int x)
{
    if(l <= t[u].l && t[u].r <= r)
    {
        if(x == 2)
        {
            t[u].add = 1-t[u].add;
            swap(t[u].sum[0],t[u].sum[1]);
            swap(t[u].lmax[0],t[u].lmax[1]);
            swap(t[u].rmax[0],t[u].rmax[1]);
            swap(t[u].ans[0],t[u].ans[1]);
        }
        else
        {
            t[u].add = x;
            t[u].sum[x] = t[u].s,t[u].sum[1-x] = 0;
            t[u].lmax[x] = t[u].s,t[u].lmax[1-x] = 0;
            t[u].rmax[x] = t[u].s,t[u].rmax[1-x] = 0;
            t[u].ans[x] = t[u].s,t[u].ans[1-x] = 0;
        }
        return;
    }
    pushdown(u);
    int mid = t[u].l+t[u].r>>1;
    if(l <= mid)cov(2*u,l,r,x);
    if(mid < r)cov(2*u+1,l,r,x);
    upd(u);
}
int ask1(int u,int l,int r)
{
    if(l <= t[u].l && t[u].r <= r)return t[u].sum[1];
    pushdown(u);
    int mid = t[u].l+t[u].r>>1,ret = 0;
    if(l <= mid)ret += ask1(2*u,l,r);
    if(mid < r)ret += ask1(2*u+1,l,r);
    return ret;
}
node ask2(int u,int l,int r)
{
    if(l <= t[u].l && t[u].r <= r)return t[u];
    pushdown(u);
    int mid = t[u].l+t[u].r>>1;
    node ret,L,R;
    if(l <= mid)L = ask2(2*u,l,r);
    if(mid < r)R = ask2(2*u+1,l,r);
    if(l <= mid && mid < r)
    {
        ret.s = L.s + R.s;
        if(L.lmax[1] == L.s)
            ret.lmax[1] = max(L.lmax[1],L.s+R.lmax[1]);
        else
            ret.lmax[1] = L.lmax[1];
        if(R.rmax[1] == R.s)
            ret.rmax[1] = max(R.rmax[1],R.s+L.rmax[1]);
        else
            ret.rmax[1] = R.rmax[1];
        ret.ans[1] = max(max(L.ans[1],R.ans[1]),L.rmax[1]+R.lmax[1]);
    }
    else if(l <= mid)ret = L;
    else if(r < mid)ret = R;
    return ret;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;i++)scanf("%d",&a[i]);
    build(1,1,n);
    while(m--)
    {
        int o,l,r;
        scanf("%d%d%d",&o,&l,&r);++l,++r;
        if(o == 0)
            cov(1,l,r,0);
        if(o == 1)
            cov(1,l,r,1);
        if(o == 2)
            cov(1,l,r,2);
        if(o == 3)
            printf("%d\n",ask1(1,l,r));
        if(o == 4)
            printf("%d\n",ask2(1,l,r).ans[1]);
//      printf("====###====\n");
//      for(int u = 1;u <= n;u++)
//      {
//          printf("id = %d (%d,%d)",u,t[u].l,t[u].r);
//          printf(" sum = %d\n",t[u].sum[1]);
//          printf(" lmax = %d\n",t[u].lmax[1]);
//          printf(" rmax = %d\n",t[u].rmax[1]);
//          printf(" ans = %d\n",t[u].ans[1]);
//      }
    }
    return 0;
}

by ydkxj @ 2024-09-05 22:09:29

唔,撸小猫


by ydkxj @ 2024-09-05 22:10:13

快来捉猫 @Lele_Programmer


by Lele_Programmer @ 2024-09-05 22:11:08

@ydkxj at 无关人物,jbl(bushi


by ydkxj @ 2024-09-05 22:12:50

@Lele_Programmer aaaaaaaaaaa????????


by MorLeaves @ 2024-09-05 22:28:25

%%%


by DWT8125 @ 2024-09-06 12:56:41

覆盖和取反tag是要分开吧


by Lele_Programmer @ 2024-09-06 19:39:44

@luxiaomao 同 @DWT8125 所说,两个 tag 最好分开,然后能 pushdown 的尽量 pushdown,修改的时候遇到要修改的节点也进行 pushdown,只要不是叶节点就 pushdown,尽量不要让一个节点同时存在两个 tag(只是一个小建议,具体 WA 原因暂不确定)


by DWT8125 @ 2024-09-06 19:51:28

@luxiaomao @Lele_Programmer 貌似不是最好分开的事。。。因为翻转tag会影响先前覆盖tag吧


by DWT8125 @ 2024-09-06 20:12:35

@luxiaomao hack:

4 1
1 1 1 1
4 1 2

您要调的可能不只是pushdown了


by Lele_Programmer @ 2024-09-06 21:44:48

@DWT8125 嗯嗯(毕竟我写了 4KB+


| 下一页