zoukankan      html  css  js  c++  java
  • 【2018.11.7】【luoguNOIp 热身赛】解题报告及总结

    reference:

    暂告一段落,做的很爽!!
    还剩5题,预计等国庆集训完再回来做

    NOIp热身赛 比赛列表

    P5142 区间方差

    这题挺模板的,暴力单点修改,推一推方差的公式,发现只需要sum和ssum(区间平方和),然后逆元啥的……自己搞(为了练手,用了扩欧,当然ksm也是过得了的)

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    template <typename T>inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define dwn(i,a,b) for(int i=a;i>=b;--i)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ee(i,u) for(int i=head[u];i;i=e[i].next)
    
    #define lson o<<1
    #define rson o<<1|1
    const int N=100010,mod=1e9+7;
    
    struct tree{
    	int l,r;
    	int sum,ssum;
    }t[N<<2];
    
    int val[N];
    int n,m;
    
    inline void exgcd(int a,int b,int &x,int &y){
    	if(!b)x=1,y=0;
    	else exgcd(b,a%b,y,x),y-=a/b*x;
    }
    
    int inv(int a){
        int x,y;
        exgcd(a,mod,x,y);
        return (x+mod)%mod;
    }
    
    inline void pushup(int o){
    	t[o].sum=(t[lson].sum+t[rson].sum)%mod;
    	t[o].ssum=(t[lson].ssum+t[rson].ssum)%mod;
    }
    
    inline void build(int o,int l,int r){
    	t[o].l=l,t[o].r=r;
    	if(l==r){
    		t[o].sum=val[l]%mod;
    		t[o].ssum=1LL*val[l]*val[l]%mod;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(lson,l,mid);
    	build(rson,mid+1,r);
    	pushup(o);
    }
    
    inline void change(int o,int pos,int k){
    	int l=t[o].l,r=t[o].r;
    	if(pos==l && pos==r){
    		t[o].ssum=1LL*k*k%mod;
    		t[o].sum=k%mod;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	if(pos<=mid)change(lson,pos,k);
    	else change(rson,pos,k);
    	pushup(o);
    }
    
    inline int query_sum(int o,int x,int y){
    	int l=t[o].l,r=t[o].r;
    	if(x<=l && r<=y){
    		return t[o].sum;
    	}
    	int res=0;
    	int mid=(l+r)>>1;
    	if(x<=mid)res=(res+query_sum(lson,x,y))%mod;
    	if(mid<y)res=(res+query_sum(rson,x,y))%mod;
    	return res;
    }
    
    inline int query_ssum(int o,int x,int y){
    	int l=t[o].l,r=t[o].r;
    	if(x<=l && r<=y){
    		return t[o].ssum;
    	}
    	int res=0;
    	int mid=(l+r)>>1;
    	if(x<=mid)res=(res+query_ssum(lson,x,y))%mod;
    	if(mid<y)res=(res+query_ssum(rson,x,y))%mod;
    	return res;
    }
    
    #undef int
    int main(){
    #define int long long
    	#ifdef WIN32
    	freopen("fangcha.txt","r",stdin);
    	#endif 
    	rd(n),rd(m);
    	rep(i,1,n)rd(val[i]);
    	build(1,1,n);
    	while(m--){
    		int op,x,k,y;
    		rd(op);
    		if(op==1){
    			rd(x),rd(k);
    			change(1,x,k);
    		}
    		else if(op==2){
    			rd(x),rd(y);
    			/*
    			方差=(a1^2+a2^2+...+an^2)/n  -  a_ba^2; 
    			*/
    			int len=inv(y-x+1);
    			int sum=query_sum(1,x,y)%mod;
    			int qsum=query_ssum(1,x,y)%mod;
    			qsum=qsum*len%mod;
    			int ba=sum*len%mod;
    			int ave=ba*ba%mod;
    			int ans=qsum-ave;
    			while(ans<0)ans+=mod;//如果不加这句只能得10 pts!!! 
    			printf("%lld
    ",ans);
    		}
    	}
    	return 0;
    }
    

    P1471 方差(上道题的哥哥)

    还要维护一个区间加操作(自己再推一遍如何更新的)

    然鹅最坑的点是加的这个数k是一个实数阿伟调了好久好久!!!!

    主要是update(int o,int x,int y,int k)
    的int k要写成 double k啊我真是个智娃。

    以后看到题上写了实数俩字儿的时候请千万小心!

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;} 
    #define rep(i,a,b) for(int i=a;i<=b;++i)
    #define dwn(i,a,b) for(int i=a;i>=b;--i)
    #define mem(a,b) memset(a,b,sizeof(a))
    #define ee(i,u) for(int i=head[u];i;i=e[i].next)
    
    #define lson o<<1
    #define rson o<<1|1
    const int N=100010;
    
    struct tree{
    	int l,r;
    	double sum,ssum,tag_add;
    }t[N<<2];
    
    double val[N];
    int n,m;
    
    inline void pushup(int o){
    	t[o].sum=(t[lson].sum+t[rson].sum);
    	t[o].ssum=(t[lson].ssum+t[rson].ssum);
    }
    
    inline void f(double delta,int o){
    	int l=t[o].l,r=t[o].r;
    	t[o].tag_add+=delta;
    	t[o].ssum=t[o].ssum+2*delta*t[o].sum+delta*delta*(r-l+1);
    	t[o].sum+=delta*(r-l+1);
    } 
    
    inline void pushdown(int o){
    	if(t[o].tag_add){
    		f(t[o].tag_add,lson);
    		f(t[o].tag_add,rson);
    		t[o].tag_add=0;
    	}
    }
    
    inline void build(int o,int l,int r){
    	t[o].tag_add=0;
    	t[o].l=l,t[o].r=r;
    	if(l==r){
    		t[o].sum=val[l];
    		t[o].ssum=val[l]*val[l];
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(lson,l,mid);
    	build(rson,mid+1,r);
    	pushup(o);
    }
    
    inline void update(int o,int x,int y,double k){
    	int l=t[o].l,r=t[o].r;
    	if(x<=l && r<=y){
    		f(k,o);
    		return ;
    	}
    	pushdown(o);
    	int mid=(l+r)>>1;
    	if(x<=mid)update(lson,x,y,k);
    	if(mid<y)update(rson,x,y,k);
    	pushup(o);
    } 
    
    inline double query_sum(int o,int x,int y){
    	int l=t[o].l,r=t[o].r;
    	if(x<=l && r<=y){
    		return t[o].sum;
    	}
    	pushdown(o);
    	double res=0;
    	int mid=(l+r)>>1;
    	if(x<=mid)res=(res+query_sum(lson,x,y));
    	if(mid<y)res=(res+query_sum(rson,x,y));
    	return res;
    }
    
    inline double query_ssum(int o,int x,int y){
    	int l=t[o].l,r=t[o].r;
    	if(x<=l && r<=y){
    		return t[o].ssum;
    	}
    	pushdown(o);
    	double res=0;
    	int mid=(l+r)>>1;
    	if(x<=mid)res=(res+query_ssum(lson,x,y));
    	if(mid<y)res=(res+query_ssum(rson,x,y));
    	return res;
    }
    
    int main(){
    	#ifdef WIN32
    	freopen("fangcha.txt","r",stdin);
    	#endif
    	rd(n),rd(m);
    	rep(i,1,n)scanf("%lf",&val[i]);
    	build(1,1,n);
    	while(m--){
    		int op,x,y;
    		double k;
    		rd(op);
    		if(op==1){
    			rd(x),rd(y);scanf("%lf",&k);
    			update(1,x,y,k);
    		}
    		else if(op==2){
    			rd(x),rd(y);
    			double ans=query_sum(1,x,y)/(y-x+1);
    			printf("%.4lf
    ",ans); 
    		}
    		else if(op==3){
    			rd(x),rd(y);
    			double sum1=query_ssum(1,x,y)/(y-x+1);
    			double sum2=query_sum(1,x,y)/(y-x+1);
    			printf("%.4lf
    ",sum1-sum2*sum2);
    		}
    	}
    	return 0;
    }
    

    P5146 最大差值[胸中的日月]

    智娃水题,由于j>i,所以对于每一个j前的数,最小值是一定的!那么我们存一下minn,不断更新ans=max(ans,x-minn)就可以O(n)啦

    P1890 gcd区间 ST表

    当你,有上线段树的冲动时,不妨看看ST表能不能搞。
    显然,gcd是满足区间可“加”性的。而有没有什么修改操作……ST表无疑是一个酷酷的选择。(而且又好写又好调)

    P2434 [SDOI2005]区间(合并区间模型)

    • 对于每个区间按照左端点从小到大排序
    • 枚举每一个区间;
      • 如果r<rang[i].l的话就输出当前区间(l,r),然后更新l=rang[i].l,r=rang[i].r;,继续去求下一个满足条件的区间。
      • else 说明两个区间有并,则更新r=max(r,range[i].r),其实左端点可以不用更新的(l=min(l,range[i].l),因为毕竟就是按照左端点来排得序嘛
    • 最后不要忘了输出l,r

    P2082 区间覆盖(加强版)上一题的弟弟

    在找到一个符合条件的区间的时候更新一下长度就好啦,没什么难的

    P5077 Tweetuzki 爱等差数列 推公式

    不开long long见祖宗

    手推一下柿子,倒序枚举,找到直接退出(这样可以保证找到的a1是最小的)。

    	rd(s); 
    	int tot=sqrt(2*s)+1;
    	dwn(i,tot,1){
    		if((s*2+i-i*i)%(2*i)==0 && (s*2+i-i*i)/*分母>0,如果不写这句会WA两个点*/){
    			printf("%lld %lld
    ",(s*2+i-i*i)/(2*i),(s*2+i-i*i)/(2*i)+i-1);
    			break;
    		}
    	}
    

    P5144 蜈蚣 前缀异或和+dp

    前缀异或和+dp

    f[i][j]表示前i个位置放了j个^符号(分成了j+1段)

    初值:f[i][0]=sum[i]

    状态转移:
    由区间[1,j-1][j,i]来更新f[i][k]

    rep(i,1,n)
    	rep(k,1,min(m,i-1))
    		rep(j,k,i)
    			f[i][k]=max(f[i][k],f[j-1][k-1]+(sum[i]^sum[j-1]));
    

    P5149 会议座位 归并排序+map

    很明显,在n<=1e5的情况下,逆序对最坏情况下是会达到100000*(100000-1)/2 == 4,999,950,000‬的!!这超出了int 的范围,要开long long.

    不要每次等WA了再重新分析数据范围,要一遍就想明白。考场上不会有提交的feedback!

    P5150 生日礼物 唯一分解定理

    一看见lcm(a,b)==n这么巧!!!
    对于n分解素数,n=p1^c1+p2^c2+p3^c3+...+pn^cn那么对于每一个质数pi,都有max(ci_a,ci_b)=ci;

    开始讨论:当ci_aci,那么b有ci+1种选法(0也要算上),同理,当ci_bci,那么a有ci+1种选法

    加起来是2ci+2种,而当ci_aci_bci的这种情况被算了两边,再-1,得对于每一个素数是2*c[i]+1种,用乘法原理乘起来即可

    不要忘了n本身是一个大质数的情况

  • 相关阅读:
    IDEA 学习笔记之 Scala项目开发
    IDEA 学习笔记之 Java项目开发
    IDEA 学习笔记之 安装和基本配置
    MongoDB 学习笔记之 索引
    MongoDB 学习笔记之 删除数据,集合,数据库
    Shiro学习(13)RememberMe
    Shiro学习(12)与Spring集成
    Shiro学习(11)缓存机制
    Shiro学习(10)Session管理
    Shiro学习(9)JSP标签
  • 原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11634657.html
Copyright © 2011-2022 走看看