zoukankan      html  css  js  c++  java
  • 题解 P5072 【[Ynoi2015] 盼君勿忘】

    在太阳西斜的这个世界里,置身天上之森。等这场战争结束之后,不归之人与望眼欲穿的众人, 人人本着正义之名,长存不灭的过去、逐渐消逝的未来。我回来了,纵使日薄西山,即便看不到未来,此时此刻的光辉,盼君勿忘。————世界上最幸福的女孩

    珂朵莉最最最最最最最珂爱了!
    闲话少说,切入正题


    第一道 Ynoi&400 题祭
    害怎么又暴露自己的菜鸡水平了
    显然,(1le n,m,a_i le 10^5) 这样友好的数据,没有修改的良心操作和可以离线的痕迹,这很显然是个莫队。
    但是我们会发现“子序列”“去重”这些东东不好计算,我们转化成贡献。

    ([l,r]) 这个区间内有一个 (x),这个 (x) 又出现了 (k) 次,我们来计算 (x) 对于 ([l,r]) 的贡献。
    很显然,([l,r])(2^{r-l+1}) 个子序列,因为每个元素只有两种状态:选或不选,那么不包含 (x) 的子序列有多少个呢?显然就有 (2^{r-l+1-k}) 个,由此,我们将两个相减就能得到包含 (x) 的子序列个数:(2^{r-l+1}-2^{r-l+1-k}) 就是包含 (x) 的子序列个数。所以 (x) 的贡献就是 (x imes (2^{r-l+1}-2^{r-l+1-k}))


    (sum_i) 为出现次数为 (i) 的和,(cnt_i)(i) 数出现的次数。
    然后我们需要一个 DS 来维护一串数量,这些数量为一个数出现的个数,需要支持快速遍历,插入和删除,显然可以用双向链表来维护。
    然后我们就可以用莫队来维护这个 (sum_i),在插入删除时维护数量链表,最后遍历链表然后根据上面的贡献公式直接累加就好了~


    还有一个问题,就是该题中我们要多次计算二的次幂,然而鹅快速幂是 (log_2 n) 的,这该怎么办?
    黑科技光速幂出现了!
    光速幂是什么?就是预处理 (2^0)(2^{sqrt n})(2^{sqrt n},2^{2 imes {sqrt{n}}},2^{3 imes {sqrt{n}}}...2^n),每个幂次我们都把它看成两个部分相乘就可以 (O(1)) 计算啦~


    还有一个重要的事情:
    能用 (a_i+a_i),不用 (a_i imes2)
    对于我这样并不怎么卡过常的蒟蒻来说这很重要,不然乘 2 试试就逝世/dk


    上代码!

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define MAXN 100010
    #define int long long//这道题的常数不怎么卡,可以这样写
    using namespace std;
    int n,m,len;
    struct node{//莫队输入
    	int l,r,cl,ind,k;
    }in[MAXN];
    inline int read()//快读
    {
        int ans=0;
        char ch=getchar();
        while (ch<'0' || ch>'9') ch=getchar();
        while (ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar();
        return ans;
    }
    inline void write(int x)
    {
        char f[200];
        int tmp=x>0?x:-x,cnt=0;
        if(x==0)putchar('0'),putchar('
    ');
        else{
        	if(x<0)putchar('-');
        	while(tmp>0)f[cnt++]=tmp%10+'0',tmp/=10;
        	while(cnt>0)putchar(f[--cnt]);
        	putchar('
    ');
        }
    }
    struct list{//手写双向链表
    	int pre[MAXN],nxt[MAXN],tot;
    	void insert(int x){nxt[tot]=x,pre[x]=tot,tot=x;}
    	void erase(int x)
    	{
    		if(x!=tot)nxt[pre[x]]=nxt[x],pre[nxt[x]]=pre[x];
    		else nxt[pre[x]]=0,tot=pre[x];
    		pre[x]=nxt[x]=0;
    	}
    }ML;
    bool cmp(node &x,node &y)//莫堆排序
    {
    	return ((x.cl!=y.cl)?(x.l<y.l):((x.cl&1)?(x.r<y.r):(x.r>y.r)));
    }
    int sum[MAXN],cnt[MAXN],a[MAXN],p1[MAXN],p2[MAXN],ans[MAXN];
    void get(int mod)//光速幂预处理
    {
    	p1[0]=p2[0]=1;
    	for(int p=1;p<=len+7;p++)
    		p1[p]=(p1[p-1]+p1[p-1])%mod;
    	for(int p=1;p<=n/len+7;p++)
    		p2[p]=p2[p-1]*p1[len]%mod; 
    }
    int Pow(int k,int mod){return p2[k/len]*p1[k%len]%mod;}//光速幂
    void add(int qwq)//莫队插入
    {
    	sum[cnt[qwq]]-=qwq;
    	if(!sum[cnt[qwq]])
    		ML.erase(cnt[qwq]);
    	cnt[qwq]++;
    	if(!sum[cnt[qwq]])
    		ML.insert(cnt[qwq]);
    	sum[cnt[qwq]]+=qwq;
    }
    void del(int qwq)//莫队删除
    {
    	sum[cnt[qwq]]-=qwq;
    	if(!sum[cnt[qwq]])
    		ML.erase(cnt[qwq]);
    	cnt[qwq]--;
    	if(!sum[cnt[qwq]])
    		ML.insert(cnt[qwq]);
    	sum[cnt[qwq]]+=qwq;
    }
    signed main()
    {
    	n=read(),m=read(); 
    	len=sqrt(n);
    	for(int p=1;p<=n;p++)
    		a[p]=read();
    	for(int p=1;p<=m;p++)
    	{
    		in[p].l=read(),in[p].r=read(),in[p].k=read();
    		in[p].ind=p,in[p].cl=(in[p].l-1)/len+1;
    	}
    	sort(in+1,in+m+1,cmp);
    	int l=1,r=0;
    	for(int p=1;p<=m;p++)
    	{
    		get(in[p].k);
    		while(l<in[p].l)del(a[l++]);
    		while(l>in[p].l)add(a[--l]);
    		while(r<in[p].r)add(a[++r]);
    		while(r>in[p].r)del(a[r--]); 
    		for(int i=ML.nxt[0];i;i=ML.nxt[i])
    			ans[in[p].ind]=(ans[in[p].ind]+((sum[i]*(Pow(in[p].r-in[p].l+1,in[p].k)-Pow(in[p].r-in[p].l+1-i,in[p].k)))%in[p].k+in[p].k)%in[p].k+in[p].k)%in[p].k;//然后是统计贡献,记得取模
    	}
    	for(int p=1;p<=m;p++)
    		write(ans[p]);//输出
    }
    

    PS:这份代码不能保证随时随地每时每刻都能 AC 这道题,因为最长的点跑了 3s,很可能评测姬任务一多然后就炸开花了

  • 相关阅读:
    linux centos7 如何安装mysql
    Json转换 在java中的应用
    最最简单的spring mvc + Maven项目
    windows下 申请免费ssl证书的方法 (letsencrypt)
    PowerDesigner中Table视图同时显示Code和Name
    在linux中 部署 mongo 数据库服务端
    Java保存图片到数据库Blob格式
    MyBatis mapper记录
    vue防止多次点击,重复请求
    金额的单位转换,元转分
  • 原文地址:https://www.cnblogs.com/thirty-two/p/14403256.html
Copyright © 2011-2022 走看看