• 洛谷 [COCI2015-2016#1] RELATIVNOST


    PS:如果读过题了可以跳过题目描述直接到题解部分
    提交链接:洛谷 [COCI2015-2016#1] RELATIVNOST

    题目

    题目描述

    您是一位计数大师,有一天您的朋友 Luka 出了一道问题来刁难您。

    Luka 是一位勤劳的画家,他的画很好,所以会有 n n n 个人来买他的画。

    画分两种,黑白画与彩色画。

    Luka 十分勤劳,所以他有无穷多的画。

    Luka 讨厌出售黑白画,所以他希望至少有 c c c 个人会买走一张彩色画。

    i i i 个人会至多购买 a i a_i ai 张彩色画, b i b_i bi 张黑白画,且它们会至少购买一幅画。

    但是,客户们只能单独购买彩色画或黑白画。

    客户们会不断改变 a i a_i ai b i b_i bi,这种改变会持续 q q q 次。

    客户以 1 ∼ n 1\sim n 1n 编号。

    您需要求出在每次改变之后,Luka 会有几种方案满足所有需求。

    为了防止输出太大,Luka 只需要您告诉他方案数   m o d     1 0 4 + 7 \bmod\ 10^4+7 mod 104+7 的值。

    输入格式

    第一行为两个整数 n , c n,c n,c

    第二行为 n n n 个整数 a i a_i ai

    第三行为 n n n 个整数 b i b_i bi

    第四行为一个整数 q q q

    接下来 q q q 行,一行三个整数 p i , a p i , b p i p_i,a_{p_i},b_{p_i} pi,api,bpi,第 i i i 行表示标号 p i p_i pi 的顾客将 a i a_i ai b i b_i bi 更换成 a p i a_{p_i} api b p i b_{p_i} bpi

    输出格式

    q q q 行,一行一个整数,第 i i i 行的值表示进行了第 i i i 次改变后,满足条件的方案数   m o d     1 0 4 + 7 \bmod\ 10^4+7 mod 104+7 的值。

    样例 #1

    样例输入 #1

    2 2
    1 1
    1 1
    1
    1 1 1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    样例输出 #1

    1
    
    • 1

    样例 #2

    样例输入 #2

    2 2
    1 2
    2 3
    2
    1 2 2
    2 2 2
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    样例输出 #2

    4
    4
    
    • 1
    • 2

    样例 #3

    样例输入 #3

    4 2
    1 2 3 4
    1 2 3 4
    1
    4 1 1
    
    • 1
    • 2
    • 3
    • 4
    • 5

    样例输出 #3

    66
    
    • 1

    提示

    样例 1 说明

    第一次改变后,我们只有唯一的一种方案,就是向两位用户都出售一张彩色画。

    数据范围及限制
    • 对于 30 % 30\% 30% 的数据,保证 n , q ≤ 1 0 3 n,q\le 10^3 n,q103
    • 对于 100 % 100\% 100% 的数据,保证 1 ≤ n , q ≤ 1 0 5 1\le n,q\le 10^5 1n,q105 1 ≤ c ≤ 20 1\le c\le 20 1c20 1 ≤ a i , b i , a p i , b p i ≤ 1 0 9 1\le a_i,b_i,a_{p_i},b_{p_i}\le 10^9 1ai,bi,api,bpi109 1 ≤ p i ≤ n 1\le p_i\le n 1pin
    说明

    本题满分 140 140 140 分。

    本题译自 Croatian Open Competition in Informatics 2015/2016 Contest #1 T5 RELATIVNOST。

    题解

    dp+线段树优化

    注意为了节约内存,我们需要把线段树的 l l l r r r省略掉,用位运算来查找。


    2022.10.26
    因为有人受我题解写得太水的影响,专门绕过一个人走过来问我,所以我决定补充一下题解。

    线段树

    对于线段树的每个节点,保存的是第 l l l r r r个人的信息,我们先不管它存的是什么信息,反正指到这个节点,就是说的这些人。
    线段树
    比如我们看到上图这个线段树,红色的数字表示节点编号,黑色的数字就表示该节点存的人的信息。

    然后问题就来了,节点里面到底存的这些人的什么信息呢?

    这当然就要说到dp的定义了。

    dp方程

    我们定义 d p i , j dp_{i,j} dpi,j表示 i i i号节点中买 j j j张彩色画的情况数。

    注意如果买画的张数多于 c c c张我们都把它的情况数计入 d p i , c dp_{i,c} dpi,c

    转移方程当然是用乘法原理直接两层循环用两个子节点更新父节点啦。

    想必做到这道题的人代码阅读能力都不弱,具体的方程就自己详见 u p d a t e update update函数内部吧。


    代码实现

    140pts

    提醒一下,洛谷上要想过一定要开O2优化!!!!!

    //洛谷 [COCI2015-2016#1] RELATIVNOST
    #pragma GCC optimize(3)
    #include
    #include
    using namespace std;
    const int mo=10007;
    int n,c;
    int a[100010];
    int b[100010];
    int q;
    int p,ap,bp;
    short t[400010][21];
    
    void in(int &x){
    	int nt;
    	x=0;
    	while(!isdigit(nt=getchar()));
    	x=nt^'0';
    	while(isdigit(nt=getchar())){
    		x=(x<<3)+(x<<1)+(nt^'0');
    	}
    }
    
    void out(register int x){
    	if(x>9) out(x/10ll);
    	putchar(x%10ll^48ll);
    }
    
    void update(int x){
    	for(int i=0;i<=c;++i){
    		t[x][i]=0;
    	}
    	for(int i=0;i<=c;++i){
    		for(int j=0;j<=c;++j){
    			t[x][min(i+j,c)]+=(1ll*t[x<<1][i]*t[x<<1|1][j])%mo;
    			t[x][min(i+j,c)]%=mo;
    		}
    	}
    }
    
    void build(int x,int l,int r){
    	if(l==r){
    		t[x][1]=a[l];
    		t[x][0]=b[l];
    		return;
    	}
    	int mid=l+r>>1;
    	build(x<<1,l,mid);
    	build(x<<1|1,mid+1,r);
    	update(x);
    }
    
    void change(int x,int l,int r,int p,int pa,int pb){
    	if(l==r){
    		t[x][1]=pa;
    		t[x][0]=pb;
    		return;
    	}
    	int mid=l+r>>1;
    	if(p<=mid){
    		change(x<<1,l,mid,p,pa,pb);
    	}
    	else{
    		change(x<<1|1,mid+1,r,p,pa,pb);
    	}
    	update(x);
    }
    
    int main(){
    	register int i,j;
    	in(n),in(c);
    	for(i=1;i<=n;++i){
    		in(a[i]);
    		a[i]%=mo;
    	}
    	for(i=1;i<=n;++i){
    		in(b[i]);
    		b[i]%=mo;
    	}
    	build(1,1,n);
    	in(q);
    	for(i=1;i<=q;++i){
    		in(p),in(ap),in(bp);
    		ap%=mo;
    		bp%=mo;
    		change(1,1,n,p,ap,bp);
    		out(t[1][c]);
    		putchar('\n');
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
  • 相关阅读:
    TCP串流场景剖析
    前端面试合集(二)
    Red-Black Tree红黑树
    李宏毅深度学习--《Unsupervised Learning:Neighbor Embedding》
    【论文写作】RSA算法的实现总体设计参考
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java高校心理咨询管理系统0e78p
    pytorch里常用操作(持续更新)
    面试经典150题
    【Web开发 | Django】数据库分流之道:探索Django多数据库路由最佳实践
    Java8流Stream的创建和操作
  • 原文地址:https://blog.csdn.net/AmyLiu_1020/article/details/127423569