WHU 1578 Fishing Dream(分块暴力)

来源:互联网 发布:淘宝3c认证在哪里 编辑:程序博客网 时间:2024/05/15 23:51
Description

    Fishing dream is a online game ran by CVTE. And you, as a crazy game player, are struggling to find your place in the ranking list.  

    To simplify the problem, we assume that all the fish in the river forms a line and numberd from 1 to N and the size of each fish is Ai. 

    Now you are required to answer M queries. For each query, you should answer what’s the minimum operations you may perform to catch all the fish numbered from L to R. 

    The operation is defined to catch a group of fish whose size forms a continuous number sequence. For example, you may catch five fish of 1, 2, 3, 4, 5 for a time but you can’t catch four fish of 1, 2, 3, 5.

    Because it’s a game, the status of fish in the river will not change after you perform your operation again and again.

Input
    The input consists of one or more test cases.
    The first line of each test case contains two numbers N and M, which denotes the number of the fish and the number of the queries. ( 1<=N, M<=10^5 )
    Then the second line follows a sequence of A, representing the size of the fish. (1<=A[i]<=10^5)
    The following M lines each describes a query of L and R. (1<=L,R<=N)
(No more than 10000 cases . No more than 20 cases with N , M more than 10000.)
Output
     For each case, output the product of M answers modulo 1 000 000 007(10^9+7).
Sample Input
3 1
1 2 3
1 3
5 3
3 2 4 2 1
1 3
1 4
2 5
Sample Output
1
6
Hint


题意:钓鱼,一段区间内只要能分成某些组,组内值连续,就可以一起钓上来(开始题意读错了

分析:分成多少组,我们考虑每个值的个数就行了,假设我们要加入u的时候:如果cnt[u]大于cnt[u-1]

和cnt[u+1]就要ans++,因为要拿出u来单独钓,同理,加入现在要删除u,那么如果cnt[u]小于cnt[u-1]且

cnt[u]小于cnt[u+1]就要ans++,因为分开了,要重新从分割点钓

#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#include<string>#include<iostream>#include<queue>#include<cmath>#include<map>#include<stack>#include<set>using namespace std;#define REPF( i , a , b ) for ( int i = a ; i <= b ; ++ i )#define REP( i , n ) for ( int i = 0 ; i < n ; ++ i )#define CLEAR( a , x ) memset ( a , x , sizeof a )const int INF=0x3f3f3f3f;typedef long long LL;const int mod=1e9+7;const int maxn=1e5+10;int num[maxn],c[maxn];int pos[maxn],cnt[maxn];struct node{    int l,r;    int id;}q[maxn];LL ans;int n,m,mi,mx;int cmp(node l1,node l2){    if(pos[l1.l]==pos[l2.l])        return l1.r<l2.r;    return pos[l1.l]<pos[l2.l];}void Add(int x){    int val=c[x];    cnt[val]++;    if(val==mi)    {        if(cnt[val+1]<cnt[val])            ans++;    }    else if(val==mx)    {        if(cnt[val-1]<cnt[val])            ans++;    }    else    {        if(cnt[val]>cnt[val-1]&&cnt[val]>cnt[val+1])            ans++;        if(cnt[val]<=cnt[val-1]&&cnt[val]<=cnt[val+1])            ans--;    }}void Sub(int x){    int val=c[x];    cnt[val]--;    if(val==mi)    {        if(cnt[val+1]<=cnt[val])            ans--;    }    else if(val==mx)    {        if(cnt[val-1]<=cnt[val])            ans--;    }    else    {        if(cnt[val]>=cnt[val-1]&&cnt[val]>=cnt[val+1])            ans--;        if(cnt[val]<cnt[val-1]&&cnt[val]<cnt[val+1])            ans++;    }}int main(){    while(~scanf("%d%d",&n,&m))    {        CLEAR(num,0);        CLEAR(cnt,0);        mi=INF;mx=-INF;        int block=(int)sqrt(1.0*n+0.5);        REPF(i,1,n)        {            scanf("%d",&c[i]);            mi=min(mi,c[i]);            mx=max(mx,c[i]);            pos[i]=(i-1)/block+1;        }        REP(i,m)        {            scanf("%d%d",&q[i].l,&q[i].r);            q[i].id=i;        }        if(n==1)        {            puts("1");            continue;        }        sort(q,q+m,cmp);        int L=1,R=0;ans=0;        LL sum=1;        for(int i=0;i<m;i++)        {            int id=q[i].id;            while(R<q[i].r) Add(++R);            while(R>q[i].r) Sub(R--);            while(L<q[i].l) Sub(L++);            while(L>q[i].l) Add(--L);            sum=(sum*ans)%mod;        }        printf("%lld\n",sum);    }    return 0;}


0 0
原创粉丝点击