• HZOI20190823模拟31题解


    题面:https://www.cnblogs.com/Juve/articles/11425141.html

    math:仔细看看其实是个水题

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define int long long
    #define re register
    using namespace std;
    const int MAXN=5e5+5;
    const int MAXM=1e6+5;
    int n,k,a[MAXN],g,sum;
    int gcd(int a,int b){
    	return b==0?a:gcd(b,a%b);
    }
    signed main(){
    	scanf("%lld%lld",&n,&k);
    	for(re int i=1;i<=n;i++) scanf("%lld",&a[i]);
    	g=k;
    	for(int i=1;i<=n;i++) g=gcd(a[i],g);
    	sum=k/g;
    	printf("%lld
    ",sum);
    	for(int i=0;i*g<k;i++){
    		printf("%lld ",i*g);
    	}
    	puts("");
    	return 0;
    }
    

    biology:dp,维护4个最大值

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define MAXN 2005
    #define re register
    #define int long long
    using namespace std;
    int n,m,a[MAXN][MAXN],b[MAXN][MAXN],ans=0,tot=0,st;
    struct node{
    	int x,y,a,b;
    	friend bool operator < (node p,node q){
    		return p.a<q.a;
    	}
    }t[MAXN*MAXN];
    bool vis[MAXN*MAXN];
    int px1,px2,px3,px4,mx1,mx2,mx3,mx4;
    signed main(){
    	scanf("%lld%lld",&n,&m);
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=m;j++)
    			scanf("%lld",&a[i][j]);
    	for(re int i=1;i<=n;i++)
    		for(re int j=1;j<=m;j++){
    			scanf("%lld",&b[i][j]);
    			if(a[i][j]==0) continue;
    			t[++tot]=(node){i,j,a[i][j],b[i][j]};
    		}
    	sort(t+1,t+tot+1);
    	t[0]=t[1];
    	for(int i=1;i<=tot;i++) if(t[i].a!=t[i-1].a) vis[i]=1;
    	for(int i=1;i<=tot;i++){
    		int x=t[i].x,y=t[i].y,res=t[i].b;
    		if(vis[i]){
    			st=i;
    			break;
    		}
    		px1=max(px1,res-x-y);
    		px2=max(px2,res-x+y);
    		px3=max(px3,res+x-y);
    		px4=max(px4,res+x+y);
    	}
    	for(int i=st;i<=tot;i++){
    		int x=t[i].x,y=t[i].y,res=0;
    		if(vis[i]){
    			mx1=max(mx1,px1);
    			mx2=max(mx2,px2);
    			mx3=max(mx3,px3);
    			mx4=max(mx4,px4);
    			px1=px2=px3=px4=0;
    		}
    		res=max(max(mx1+x+y,mx2+x-y),max(mx3-x+y,mx4-x-y))+t[i].b;
    		px1=max(px1,res-x-y);
    		px2=max(px2,res-x+y);
    		px3=max(px3,res+x-y);
    		px4=max(px4,res+x+y);
    		ans=max(ans,res);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    /*
    3 3
    0 6 8
    1 6 1
    0 6 8
    0 1 2
    3 4 5
    0 6 7
    */
    

    english:

    ans1用单调栈处理出每一个ai,它作为最大值的区间,然后维护前缀和,sum[i][j]表示前j个数第i位上有几个1

    ans2用可持久化01trie做

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define int long long
    using namespace std;
    const int MAXN=1e5+5;
    const int mod=1e9+7;
    int n,a[MAXN],opt,sum[22][MAXN],ans1=0,ans2=0;
    int sta[MAXN],top=0,l[MAXN],r[MAXN],tot=0;
    int tr[MAXN*22][2],size[MAXN*22],root[MAXN];
    void insert(int &now,int pre,int val,int i){
    	now=++tot;
    	size[now]=size[pre]+1;
    	if(i<0) return ;
    	int p=(val>>i)&1;
    	tr[now][p^1]=tr[pre][p^1];
    	insert(tr[now][p],tr[pre][p],val,i-1);
    	size[now]=size[tr[now][0]]+size[tr[now][1]];
    }
    int query(int rt,int x,int y){
    	int res=0;
    	for(int i=20;i>=0;i--){
    		int p=(x>>i)&1,q=(y>>i)&1;
    		if(!q){
    			(res+=size[tr[rt][p^1]])%=mod;
    			rt=tr[rt][p];
    		}
    		else rt=tr[rt][p^1];
    		if(!rt) break;
    	}
    	return res;
    }
    signed main(){
    	scanf("%lld%lld",&n,&opt);
    	for(int i=1;i<=n;i++){
    		scanf("%lld",&a[i]);
    		insert(root[i],root[i-1],a[i],20);
    		int tmp=a[i];
    		for(int j=0;j<=20;j++){
    			sum[j][i]=sum[j][i-1];
    			if((a[i]>>j)&1) sum[j][i]++;
    		}
    	}
    	for(int i=0;i<=20;i++) sum[i][n+1]=sum[i][n],sum[i][0]=0;
    	for(int i=1;i<=n;i++){
    		while(top!=0&&a[sta[top]]<a[i]) top--;
    		if(top==0) l[i]=1;
    		else l[i]=sta[top]+1;
    		sta[++top]=i;
    	}
    	top=0;
    	for(int i=n;i>=1;i--){
    		while(top!=0&&a[sta[top]]<=a[i]) top--;
    		if(top==0) r[i]=n+1;
    		else r[i]=sta[top];
    		sta[++top]=i;
    	}
    	for(int i=1,res;i<=n;i++){
    		res=0;
    		if(l[i]==r[i]) continue;
    		for(int j=0;j<=20;j++){
    			(res+=(((sum[j][i]-sum[j][l[i]-1])*((r[i]-i)-(sum[j][r[i]-1]-sum[j][i-1])))<<j))%=mod;
    			(res+=(((sum[j][r[i]-1]-sum[j][i-1])*((i-l[i]+1)-(sum[j][i]-sum[j][l[i]-1])))<<j))%=mod;
    		}
    		(ans1+=res*a[i]%mod)%=mod;
    		res=0;
    		if(i-l[i]<r[i]-i-1){
    			for(int j=l[i];j<=i;j++)
    				(res+=(query(root[r[i]-1],a[j],a[i])-query(root[i-1],a[j],a[i])+mod)%mod)%=mod;
    		}else{
    			for(int j=i;j<r[i];j++)
    				(res+=(query(root[i],a[j],a[i])-query(root[l[i]-1],a[j],a[i])+mod)%mod)%=mod;
    		}
    		(ans2+=(res*a[i]%mod))%=mod;
    	}
    	if(opt==1) printf("%lld
    ",ans1%mod);
    	else if(opt==2) printf("%lld
    ",ans2%mod);
    	else printf("%lld
    %lld
    ",ans1%mod,ans2%mod);
    	return 0;
    }
    
  • 相关阅读:
    mybatis-01-简单概述基础点
    04-书城缺少方法
    03-书城bean类中的id缺少get属性
    02-书城传参类型异常
    执行Oracle存储过程报权限不足的解决方法
    创建表空间及用户的SQL
    Oracle instr函数与SqlServer charindex的区别
    利用ExtJS导出Excel
    Java循环日期
    Oracle给不同组数据添加顺序
  • 原文地址:https://www.cnblogs.com/Juve/p/11425218.html
Copyright © 2020-2023  润新知