zoukankan      html  css  js  c++  java
  • LUOGU P3759 [TJOI2017]不勤劳的图书管理员(树套树)

    传送门

    解题思路

      和以前做过的一道题有点像,就是区间逆序对之类的问题,用的是(BIT)套权值线段树,交换时讨论一下计算答案。。跑的不如暴力快。。

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    
    using namespace std;
    const int N=50005;
    const int M=N*200;
    const int MOD=1e9+7;
    typedef long long LL;
    
    inline int rd(){
    	int x=0,f=1; char ch=getchar();
    	while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
    	while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return f?x:-x;
    }
    
    int n,m,a[N],val[N],tot,rt[N];
    LL ans;
    
    struct Segment_Tree{
    	int sum[M],num[M],ls[M],rs[M];
    	void update_num(int &x,int l,int r,int pos,int k){
    		if(!x) x=++tot; num[x]+=k; num[x]%=MOD;
    		if(l==r) return; int mid=(l+r)>>1; 
    		if(pos<=mid) update_num(ls[x],l,mid,pos,k);
    		else update_num(rs[x],mid+1,r,pos,k);
    	}
    	void update_sum(int &x,int l,int r,int pos,int k){
    		if(!x) x=++tot; (sum[x]+=k)%=MOD; 
    		if(l==r) return; int mid=(l+r)>>1;
    		if(pos<=mid) update_sum(ls[x],l,mid,pos,k);
    		else update_sum(rs[x],mid+1,r,pos,k);
    	}
    	int query_sum(int x,int l,int r,int L,int R){
    		if(!x) return 0; if(L<=l && r<=R) return sum[x];
    		int mid=(l+r)>>1,ret=0;
    		if(L<=mid) ret+=query_sum(ls[x],l,mid,L,R);
    		if(mid<R) (ret+=query_sum(rs[x],mid+1,r,L,R))%=MOD;
    		return ret;
    	}
    	int query_num(int x,int l,int r,int L,int R){
    		if(!x) return 0; if(L<=l && r<=R) return num[x];
    		int mid=(l+r)>>1,ret=0;
    		if(L<=mid) ret+=query_num(ls[x],l,mid,L,R);
    		if(mid<R) (ret+=query_num(rs[x],mid+1,r,L,R))%=MOD;
    		return ret;
    	}
    }tree2;
    
    struct BIT{
    	inline void add(int x,int k){
    		for(int i=x;i<=n;i+=i&-i) {
    			tree2.update_num(rt[i],1,50000,a[x],k);
    			tree2.update_sum(rt[i],1,50000,a[x],k*val[x]);
    		}
    	}
    	inline int query_sum(int l,int r,int L,int R){
    		if(l>r || L>R) return 0; int ret=0;
    		for(int i=r;i;i-=i&-i) (ret+=tree2.query_sum(rt[i],1,50000,L,R))%=MOD;
    		for(int i=l-1;i;i-=i&-i) (ret-=tree2.query_sum(rt[i],1,50000,L,R))%=MOD;
    		return (ret+MOD)%MOD;
    	}
    	inline int query_num(int l,int r,int L,int R){
    		if(l>r || L>R) return 0; int ret=0;
    		for(int i=r;i;i-=i&-i) (ret+=tree2.query_num(rt[i],1,50000,L,R))%=MOD;
    		for(int i=l-1;i;i-=i&-i) (ret-=tree2.query_num(rt[i],1,50000,L,R))%=MOD;
    		return (ret+MOD)%MOD;
    	}
    }tree1;
    
    int main(){
    	n=rd(),m=rd(); int x,y,tmp,num,num1,num2;
    	for(int i=1;i<=n;i++){
    		a[i]=rd(),val[i]=rd(); tree1.add(i,1);
    		ans+=tree1.query_sum(1,i,a[i]+1,50000);
    		ans+=1ll*tree1.query_num(1,i,a[i]+1,50000)*val[i]%MOD;
    		ans%=MOD;
    	}	LL sum;
    	while(m--){
    		x=rd(),y=rd(); if(x>y) swap(x,y);
    		if(x==y) {printf("%lld
    ",ans); continue;}
    		if(a[x]<a[y]) (ans+=val[x]+val[y])%=MOD;
    		else (ans-=val[x]+val[y])%=MOD;
    		tmp=tree1.query_sum(x+1,y-1,min(a[x],a[y]),max(a[x],a[y]));
    		num=tree1.query_num(x+1,y-1,min(a[x],a[y]),max(a[x],a[y]));
    		num1=tree1.query_num(x+1,y-1,1,min(a[x],a[y])-1);
    		num2=tree1.query_num(x+1,y-1,max(a[x],a[y])+1,50000);
    		if(a[x]<a[y]) ans+=tmp*2%MOD+1ll*num*(val[x]+val[y])%MOD,ans%=MOD;
    		else ans-=tmp*2%MOD+1ll*num*(val[x]+val[y])%MOD,ans%=MOD;
    		sum=1ll*(val[y]-val[x])*num1%MOD+1ll*(val[x]-val[y])*num2%MOD; sum%=MOD;
    		(ans+=sum)%=MOD;
    		tree1.add(x,-1); tree1.add(y,-1); swap(a[x],a[y]); swap(val[x],val[y]);
    		tree1.add(x,1); tree1.add(y,1); ans=(ans+MOD)%MOD; printf("%lld
    ",ans);
    	}
    	return 0;
    }	
    
  • 相关阅读:
    利用ArcToolBox ModelBuider进行数据处理
    【转】C#中通过API调用获取文件图标
    【转】利用C#实现标注式消息提示窗口
    【转】在C#2005中创建快捷方式
    爱一个人好难
    【转】C#获取文件与文件夹默认图标
    【转】远程教育理论中几个基本概念的探讨2
    【转】C#中Bitmap类实现对图像操作的一些方法
    【转】C#启动外部程序
    WshShortcut 对象说明
  • 原文地址:https://www.cnblogs.com/sdfzsyq/p/10430966.html
Copyright © 2011-2022 走看看