zoukankan      html  css  js  c++  java
  • 线段树 洛谷P3932 浮游大陆的68号岛

    P3932 浮游大陆的68号岛

    题目描述

    妖精仓库里生活着黄金妖精们,她们过着快乐,却随时准备着迎接死亡的生活。

    换用更高尚的说法,是随时准备着为这个无药可救的世界献身。

    然而孩子们的生活却总是无忧无虑的,幼体的黄金妖精们过着天真烂漫的生活,自然也无暇考虑什么拯救世界之类的重任。

    有一天小妖精们又在做游戏。这个游戏是这样的。

    妖精仓库的储物点可以看做在一个数轴上。每一个储物点会有一些东西,同时他们之间存在距离。

    每次他们会选出一个小妖精,然后剩下的人找到区间[l,r]储物点的所有东西,清点完毕之后问她,把这个区间内所有储物点的东西运到另外一个仓库的代价是多少?

    比如储物点i有x个东西,要运到储物点j,代价为

    (x×dist(i,j))

    dist就是仓库间的距离。

    当然啦,由于小妖精们不会算很大的数字,因此您的答案需要对19260817取模。

    输入输出格式

    输入格式:

    第一行两个数表示n,m

    第二行n−1个数,第i个数表示第i个储物点与第i+1个储物点的距离

    第三行n个数,表示每个储物点的东西个数

    之后m行每行三个数x l r

    表示查询要把区间[l,r]储物点的物品全部运到储物点x的花费

    输出格式:

    对于每个询问输出一个数表示答案

    对于输入的距离,我们可以通过前缀和求出每个点的具体位置。

    这样我们就可以知道任意两个点的距离了。

    然后发现这道题没有修改操作,(好吧其实也没什么用。。。)

    查询的话,推个式子就好了。

    [ans_{l,r}=sum_{i=l}^ra(i)*abs(dis(i)-dis(x)) ]

    一开始的时候,我是这么推得,(错的。)

    [ans_{l,r}=sum_{i=l}^ra(i)*abs(dis(i)-dis(x)) \=abs(sum_{i=l}^ra(i)*dis(i)-sum_{i=l}^ra(i)*dis[x]) ]

    显然,对于abs的处理是错误的。

    那么思博了一下,发现自己想的简单了,需要分情况讨论。

    所以可以得出三个式子:

    一、 x<l 时

    [ans_{l,r}=sum_{i=l}^ra(i)*(dis(i)-dis(x)) \=sum_{i=l}^ra(i)*dis(i)-dis(x)*sum_{i=l}^ra(i) ]

    二、(x>r)

    [ans_{l,r}=sum_{i=l}^ra(i)*(dis(x)-dis(i)) \=dis(x)*sum_{i=l}^ra(i)-sum_{i=l}^ra(i)*dis(i) ]

    三、(lleq xleq r)

    [ans_{l,r}=dis(x)*sum_{i=l}^{x-1}a(i)-sum_{i=l}^{x-1}a(i)*dis(i)+sum_{i=x+1}^ra(i)*dis(i)-dis(x)*sum_{i=x+1}^ra(i) ]

    就可以发现(sum)里面只有(a(i))(a(i)*dis(i)),那么直接线段树维护套上式子就可以了。

    另外,难得思博。。。

    #include<iostream>
    #include<cstdio>
    #define ls(o) o<<1
    #define rs(o) o<<1|1
    #define int long long
    using namespace std;
    const int wx=1000017;
    const int mod=19260817;
    inline int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
    	return sum*f;
    }
    struct val_tree{
    	int l,r,sum1,sum2,tag;
    	#define sum1(o) t[o].sum1
    	#define sum2(o) t[o].sum2
    	#define tag(o) t[o].tag
    }t[wx*4];
    int a[wx];
    int dis[wx],w[wx];
    int n,m;
    int Abs(int a){
    	if(a<0)return -a;
    	return a;
    }
    void up(int o){
    	sum1(o)=(sum1(ls(o))+sum1(rs(o)))%mod;
    	sum2(o)=(sum2(ls(o))+sum2(rs(o)))%mod;
    }
    void build(int o,int l,int r){
    	t[o].l=l;t[o].r=r;
    	if(l==r){sum1(o)=a[l]%mod;sum2(o)=(a[l]%mod*w[l]%mod)%mod;return;}
    	int mid=t[o].l+t[o].r>>1;
    	if(l<=mid)build(ls(o),l,mid);
    	if(r>mid)build(rs(o),mid+1,r);
    	up(o);
    //	printf("%d %d %d %d
    ",t[o].l,t[o].r,sum1(o),sum2(o));
    }
    int query_a(int o,int l,int r){
    	if(l<=t[o].l&&t[o].r<=r){
    		return sum1(o)%mod;
    	}
    	int mid=t[o].l+t[o].r>>1;
    	int sum=0;
    	if(l<=mid)sum+=query_a(ls(o),l,r),sum%=mod;
    	if(r>mid)sum+=query_a(rs(o),l,r),sum%=mod;
    	return sum%mod;
    }
    int query_b(int o,int l,int r){
    	if(l<=t[o].l&&t[o].r<=r){
    		return sum2(o)%mod;
    	}
    	int mid=t[o].l+t[o].r>>1;
    	int sum=0;
    	if(l<=mid)sum+=query_b(ls(o),l,r),sum%=mod;
    	if(r>mid)sum+=query_b(rs(o),l,r),sum%=mod;
    	return sum%mod;
    }
    signed main(){
    //	freopen("001.in","r",stdin);
    	n=read();m=read();
    	for(int i=1;i<n;i++)dis[i]=read();
    	w[1]=1;
    	for(int i=2;i<=n;i++)w[i]=w[i-1]+dis[i-1];
    	for(int i=1;i<=n;i++)w[i]%=mod;
    	for(int i=1;i<=n;i++)a[i]=read()%mod;
    	build(1,1,n);
    	for(int i=1;i<=m;i++){
    		int x,l,r;
    		x=read();l=read();r=read();
    		if(x<l){
    			printf("%lld
    ",(query_b(1,l,r)-((query_a(1,l,r))%mod*(w[x]%mod))%mod+20*mod)%mod);
    		}
    		else if(x>r){
    			printf("%lld
    ",(((query_a(1,l,r))%mod*(w[x]%mod))%mod-query_b(1,l,r)+20*mod)%mod);
    		}
    		else{
    			printf("%lld
    ",(((query_a(1,l,x-1)%mod)*(w[x]%mod))%mod-query_b(1,l,x-1)+query_b(1,x+1,r)-((query_a(1,x+1,r)%mod)*(w[x]%mod))%mod+20*mod)%mod);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    消除醉酒痛苦的九种食品
    要成功,就马上准备有所付出吧!这就是每天你应该养成的习惯。
    赞美
    人的一生究竟需要多少钱?
    试试看
    ubuntu 环境变量PATH的修改[转]
    Ubuntu netsnmp安装
    ubuntu终止进程的方法
    Linux(ubuntu)下MySQL整个数据库的备份与还原 Linux下MySQL整个数据库的备份与还原[转]
    Ubuntu防火墙 UFW 设置
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9756267.html
Copyright © 2011-2022 走看看