首页 > 代码库 > CF788E:New task

CF788E:New task

n个数字中,每个数有数字A和属性B,每次操作将某个点x的属性B改变为0或1,求满足这样要求的子序列的个数:

下标a<b<c<d<e,而Aa<=Ab=Ac=Ad>=Ae且Bb=Bc=Bd=1。

区间操作,首推线段树!(然后就不会了,跑去看别人的代码)

是这样的,重点在于中间那三个点,因为我们的修改操作只会影响修改的点的值的答案。

直接维护一个这样的子序列不太容易,所以多维护Aa<=Ab和Aa<=Ab=Ac和Ac=Ad>=Ae和Ad>=Ae的序列,然后线段树up的时候才可以左右合并答案。

大体思路就这样,由于线段树是要按照值来建的,也就是给每个值一棵线段树,为方便调值先离散化。

Aa<=Ab和Ad>=Ae即每个点左边<=它和右边<=它的数,可以用树状数组预处理,详见代码。

线段树中的信息用到“当前这棵子线段树的数的个数”size,以及上面提到的四个序列长度A,AB,BC,C,还有答案ABC。

在线段树叶子节点只算A,C和size,其他数组慢慢合并,详见代码中up。

技术分享
  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<algorithm>
  4 #include<cstdlib>
  5 #include<cstring>
  6 //#include<iostream>
  7 using namespace std;
  8 
  9 int n;
 10 #define maxn 200011
 11 struct BIT
 12 {
 13     int a[maxn];
 14     void clear() {memset(a,0,sizeof(a));}
 15     int lowbit(int x) {return x&-x;}
 16     void add(int x,int v)
 17     {
 18         for (;x<=n;x+=lowbit(x)) a[x]+=v;
 19     }
 20     int query(int x)
 21     {
 22         int ans=0;
 23         for (;x;x-=lowbit(x)) ans+=a[x];
 24         return ans;
 25     }
 26 }bit;
 27 const int mod=1000000007;
 28 int Left[maxn],Right[maxn];
 29 #define maxs 2000011
 30 struct segmenttree
 31 {
 32     struct Node
 33     {
 34         int size,A,C,AB,BC,ABC;
 35         int son[2];
 36     }a[maxs];
 37     int size;
 38     segmenttree() {size=0;}
 39     void up(int x)
 40     {
 41         const int &p=a[x].son[0],&q=a[x].son[1];
 42         a[x].size=a[p].size+a[q].size;
 43         a[x].A=(a[p].A+a[q].A)%mod;
 44         a[x].C=(a[p].C+a[q].C)%mod;
 45         a[x].AB=(a[p].AB+a[q].AB+a[p].A*1ll*a[q].size)%mod;
 46         a[x].BC=(a[p].BC+a[q].BC+a[p].size*1ll*a[q].C)%mod;
 47         a[x].ABC=(a[p].ABC+a[q].ABC+1ll*a[p].A*a[q].BC+1ll*a[p].AB*a[q].C)%mod;
 48     }
 49     void modify(int &x,int L,int R,int id,int v)
 50     {
 51         if (!x) x=++size;
 52         if (L==R)
 53         {
 54             a[x].size=v*1;
 55             a[x].A=v*Left[id];
 56             a[x].C=v*Right[id];
 57             a[x].AB=a[x].BC=a[x].ABC=0;
 58             a[x].son[0]=a[x].son[1]=0;
 59         }
 60         else
 61         {
 62             const int mid=(L+R)>>1;
 63             if (id<=mid) modify(a[x].son[0],L,mid,id,v);
 64             else modify(a[x].son[1],mid+1,R,id,v);
 65             up(x);
 66         }
 67     }
 68 }seg;
 69 struct Point
 70 {
 71     int v,id;
 72     bool operator < (const Point &b) const {return v<b.v;}
 73 }b[maxn];
 74 int a[maxn],cnt=0;
 75 int root[maxn];
 76 int main()
 77 {
 78     scanf("%d",&n);
 79     for (int i=1;i<=n;i++) scanf("%d",&b[b[i].id=i].v);
 80     sort(b+1,b+1+n);
 81     a[b[1].id]=cnt=1;
 82     for (int i=2;i<=n;i++)
 83     {
 84         if (b[i].v!=b[i-1].v) cnt++;
 85         a[b[i].id]=cnt;
 86     }
 87     memset(Left,0,sizeof(Left));
 88     memset(Right,0,sizeof(Right));
 89     bit.clear();
 90     for (int i=1;i<=n;i++)
 91     {
 92         Left[i]=bit.query(a[i]);
 93         bit.add(a[i],1);
 94     }
 95     bit.clear();
 96     for (int i=n;i>=1;i--)
 97     {
 98         Right[i]=bit.query(a[i]);
 99         bit.add(a[i],1);
100     }
101     int ans=0;
102     memset(root,0,sizeof(root));
103     for (int i=1;i<=n;i++)
104     {
105         ans=(ans-seg.a[root[a[i]]].ABC+mod)%mod;
106         seg.modify(root[a[i]],1,n,i,1);
107         ans=(ans+seg.a[root[a[i]]].ABC)%mod;
108     }
109     int m,x,y;
110     scanf("%d",&m);
111     for (int i=1;i<=m;i++)
112     {
113         scanf("%d%d",&x,&y);
114         ans=(ans-seg.a[root[a[y]]].ABC+mod)%mod;
115         seg.modify(root[a[y]],1,n,y,x-1);
116         ans=(ans+seg.a[root[a[y]]].ABC)%mod;
117         printf("%d\n",ans);
118     }
119     return 0;
120 }
View Code

 

CF788E:New task