hdu 3854 Glorious Array(一般)

Problem Description
You are given a array with N nodes. The array nodes are numbered from 1 to N ( represented by a_i ). In the start, the color
of any node in the array is white or black. We define that the "distance" between a and b is min{a_i| a<=i<=b} if a-th and bth
nodes have diffrerent color, or infinite if they have the same color.
We will ask you to perfrom some instructions of the following form:
0 i : change the color of the i-th node (from white to black, or from black to white);
or
1 : ask for the kinds of diffrent pair of nodes' distance is less than K
 


Input
The first line contains a positive integer: the number of test cases, at most 100.
After that per test case:
One line with three integers N, m and K (1 ≤ N, m ≤ 1 00000, K ≤ 1000000): the length of the array, the number of
instructions and K which used in operation 1 .
Then comes a line with N intergers a_i (|a_i|<10000000).
A line with N intergers c_i (c_i = 0(white) or 1(black)), which reprsent the color of N nodes.
Next m lines, each will be a instruction described above.
 


Output
one interger for each operation 1.
 


Sample Input
1 5 3 2 2 3 1 4 2 0 1 0 1 1 1 0 2 1
 


Sample Output
5 6


 

//

题目描述:
给你n个数,和每个数字的状态(0或者1)。
有两种操作:
第一种:翻转某个数字的状态。
第二种:询问,要求输入满足条件的i, j组合个数。
一个满足条件的i,j要求:
A:1 <= i <= j <= n
B: i和j数字的状态不同
C:i和j的闭区间内的数字的最小值小于k(k由输入给定)
解题报告:
对于一开始的输入先求出组合个数。
然后对于每次的翻转状态,更新组合个数:
比如翻转i,如果x[i] < k, 那么只需看i左侧有多少个0或者1(具体看x[i]当前状态),和i右侧有多少个0或者1(同上),就可以知道这次翻转具体变化了多少,具体的实现可以用树状数组。
如果x[i] > k,初始化时记下在i左侧最近的小于k的数字的位置L[i],同理R[i]。
找到L[i]左侧0或者1的个数和R[i]右侧0或者1的个数,就是这次变化的个数。
应该比较好理解。

 

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<string>
#include<cstring>
#include<set>
#include<map>
#include<list>
#include<queue>
#include<vector>
#define tree int o,int l,int r
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define lo o<<1
#define ro o<<1|1
#define ULL unsigned long long
#define LL long long
#define inf 0x7fffffff
#define eps 1e-7
#define N 100009
using namespace std;
int T,n,m,k,t,maxv,x;
int cl[N],c[N];
int l[N],r[N];
bool val[N];
LL ans;
void init()
{
    ans=0;
    memset(c,0,sizeof(c));
    memset(cl,0,sizeof(cl));
}
void add(int x,int v)
{
    while(x<N)
    {
        c[x]+=v;
        x+=x&-x;
    }
}
int sum(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=c[x];
        x-=x&-x;
    }
    return ans;
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("ex.in","r",stdin);
#endif
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d%d",&n,&m,&k);
        init();
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&x);
            if(x<k)
                val[i]=0;
            else
                val[i]=1;
        }
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&cl[i]);
            if(cl[i])
                add(i,cl[i]);
        }
        int x=0;
        for(int i=1; i<=n; i++)
        {
            if(val[i]==0)
            {
                for(int j=i-1; j>x; j--)
                    l[j]=x,r[j]=i;

                x=i;

                l[i]=i;
                r[i]=i;/////////////////
            }
        }
        for(int j=x+1; j<=n; j++)
            l[j]=x,r[j]=n+1;

        for(int i=1; i<=n; i++)
        {
            if(val[i]==0)//////////////
            {
                ans+=i-1;
                t=i-1;
            }
            else
            {
                ans+=l[i];
                t=l[i];
            }

            int num=sum(t),all=t;
            if(cl[i]==1)
            {
                t=num;
            }
            else
                t=(all-num);
            ans-=t;

        }
        while(m--)
        {
            scanf("%d",&x);
            if(x)
            {
                printf("%I64d\n",ans);
            }
            else
            {
                scanf("%d",&x);

//                        cout<<"x="<<x<<endl;
                if(val[x]==0)
                {
//                    cout<<"========"<<endl;
                    int num=sum(n),t,all=n-1;
                    if(cl[x]==1)
                    {
                        num--;
//                        cout<<"num="<<num<<endl;
                        t=num-(all-num);
                    }
                    else
                        t=(all-num)-num;
                    ans+=t;
                }
                else
                {
                    int t,all=n-(r[x]-l[x]-1);
                    int num=sum(n)-sum(r[x]-1)+sum(l[x]);
                    if(cl[x]==1)
                    {
                        t=num-(all-num);
                    }
                    else
                        t=(all-num)-num;
                    ans+=t;
                }
                cl[x]=!cl[x];
                if(!cl[x])
                    add(x,-1);
                else
                    add(x,1);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2013-08-28 11:52  baoff  阅读(187)  评论(0编辑  收藏  举报