• NPY and girls


    NPY and girls

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5145

    莫队算法

    注意到没有修改区间的操作,使用莫队算法:将整个区间分成若干个块,将询问区间按块优先升序排序,同块内按区间右界升序排序,添加一个元素,满足条件的值sum就变为sum=(sum*times[a[r]]/(r-l+1));减少一个值同理。从第一个区间一直推到最后一个区间即可。(之前TLE一直以为是区间大小的问题,现在发现是这句话while(x<0)x+=M,不过因为这题M比较大,改改区间居然被我水过去了...)

    代码如下:

      1 #include<cstdio>
      2 #include<cmath>
      3 #include<algorithm>
      4 #include<cstring>
      5 #define N 30005
      6 #define M 1000000007
      7 #define LL long long
      8 #define B 250/**((int)sqrt((double)n)) sqrt(n) will be TLE**/
      9 #define mst(x) memset(x,0,sizeof(x))
     10 using namespace std;
     11 LL times[N];
     12 LL T,n,m,x,y;
     13 LL a[N];
     14 struct nod{
     15     LL l,r,no,value;
     16 }q[N];
     17 LL exGCD(LL a,LL b){
     18     if(b==0){
     19         x=1;
     20         y=0;
     21         return a;
     22     }
     23     LL r=exGCD(b,a%b);
     24     LL tmp=x;
     25     x=y;
     26     y=tmp-(a/b)*y;
     27     return r;
     28 }
     29 bool cmp_by_range(nod x,nod y){
     30     if(x.l/B==y.l/B){
     31         return x.r<y.r;
     32     }else return (x.l/B<y.l/B);
     33 }
     34 bool cmp_by_no(nod x,nod y){
     35     return x.no<y.no;
     36 }
     37 void init(){
     38     mst(times);
     39     scanf("%I64d%I64d",&n,&m);
     40     for(LL i=0;i<n;++i)
     41         scanf("%I64d",&a[i]);
     42     for(LL i=0;i<m;++i){
     43         LL l,r;
     44         scanf("%I64d%I64d",&l,&r);
     45         l--,r--;
     46         q[i].l=l;
     47         q[i].r=r;
     48         q[i].no=i;
     49         q[i].value=0;
     50     }
     51     sort(q,q+m,cmp_by_range);
     52 }
     53 void solve(){
     54     LL l=q[0].l,r=q[0].r,sum=1;
     55     times[a[l]]++;
     56     for(LL i=l+1;i<=r;++i){
     57         times[a[i]]++;
     58         exGCD(times[a[i]],M);
     59         while(x<0)x+=M;
     60         sum=((sum*(i-l+1))%M*x)%M;
     61     }
     62     q[0].value=sum;
     63     for(LL i=1;i<m;++i){
     64         //l=q[i-1].l,r=q[i-1].r;
     65         while(r<q[i].r){
     66             r++;
     67             times[a[r]]++;
     68             exGCD(times[a[r]],M);
     69             while(x<0)x+=M;
     70             sum=((sum*(r-l+1))%M*x)%M;
     71         }
     72         while(r>q[i].r){
     73             exGCD((r-l+1),M);
     74             while(x<0)x+=M;
     75             sum=((sum*times[a[r]])%M*x)%M;
     76             times[a[r]]--;
     77             r--;
     78         }
     79         while(l<q[i].l){
     80             exGCD((r-l+1),M);
     81             while(x<0)x+=M;
     82             sum=((sum*times[a[l]])%M*x)%M;
     83             times[a[l]]--;
     84             l++;
     85         }
     86         while(l>q[i].l){
     87             l--;
     88             times[a[l]]++;
     89             exGCD(times[a[l]],M);
     90             while(x<0)x+=M;
     91             sum=((sum*(r-l+1)%M)*x)%M;
     92         }
     93         q[i].value=sum;
     94     }
     95 }
     96 int main(void){
     97     scanf("%I64d",&T);
     98     while(T--){
     99         init();
    100         solve();
    101         sort(q,q+m,cmp_by_no);
    102         for(LL i=0;i<m;++i)
    103             printf("%I64d
    ",q[i].value);
    104     }
    105 }
  • 相关阅读:
    置换及Polya定理
    题解 UVa10943
    Error applying site theme: A theme with the name "Jet 1011" and version already exists on the server.
    用shtml来include网页文件
    SQL 2005 附加数据库出错"解决方法
    SVN 配置 入门教程
    Oracle .Net Develoer
    JdbcTemplate完全学习
    SVD外积展开式
    初识 Nslookup 命令
  • 原文地址:https://www.cnblogs.com/barrier/p/5769673.html
Copyright © 2020-2023  润新知