【BZOJ3939】Cow Hopscotch(动态开点线段树)
题意:
就像人类喜欢跳格子游戏一样,FJ的奶牛们发明了一种新的跳格子游戏。虽然这种接近一吨的笨拙的动物玩跳格子游戏几乎总是不愉快地结束,但是这并没有阻止奶牛们在每天下午参加跳格子游戏
游戏在一个R*C的网格上进行,每个格子有一个取值在1-k之间的整数标号,奶牛开始在左上角的格子,目的是通过若干次跳跃后到达右下角的格子,当且仅当格子A和格子B满足如下条件时能从格子A跳到格子B:
1.B格子在A格子的严格右方(B的列号严格大于A的列号)
2.B格子在A格子的严格下方(B的行号严格大于A的行号)
3.B格子的标号和A格子的标号不同
请你帮助奶牛计算出从左上角的格子到右下角的格子一共有多少种不同的方案
n,m<=750,k<=n*m
思路:这题是金组的数据范围
在铜组因为数据小 裸的dp可做 金组需要优化
\[ dp[i,j]= \sum_{x=1}^{i-1} \sum_{y=1}^{j-1} dp[x,y] (a[i,j]<>a[x,y]) \]
转化为左上角的所有方案-该颜色的所有方案
因为只要求保存一个版本
可以用一棵动态开点的线段树解决
修改时使用类似于主席树的方法
1 const mo=1000000007; 2 var t:array[0..7000000]of record 3 l,r,s:longint; 4 end; 5 6 sum,a,dp:array[0..800,0..800]of longint; 7 root:array[0..1000000]of longint; 8 f:array[0..800]of longint; 9 n,m,i,j,s1,s2,cnt,k:longint; 10 11 procedure pushup(x:longint); 12 var l,r:longint; 13 begin 14 l:=t[x].l; r:=t[x].r; 15 t[x].s:=(t[l].s+t[r].s) mod mo; 16 end; 17 18 procedure update(var p:longint;l,r,x,v:longint); 19 var mid:longint; 20 begin 21 if p=0 then 22 begin 23 inc(cnt); p:=cnt; 24 end; 25 if l=r then 26 begin 27 t[p].s:=(t[p].s+v) mod mo; exit; 28 end; 29 mid:=(l+r)>>1; 30 if x<=mid then update(t[p].l,l,mid,x,v) 31 else update(t[p].r,mid+1,r,x,v); 32 pushup(p); 33 end; 34 35 function query(p,l,r,x,y:longint):longint; 36 var mid:longint; 37 begin 38 39 if (p=0)or(x>y) then exit(0); 40 if (x<=l)and(y>=r) then exit(t[p].s); 41 mid:=(l+r)>>1; 42 query:=0; 43 if x<=mid then query:=(query+query(t[p].l,l,mid,x,y)) mod mo; 44 if y>mid then query:=(query+query(t[p].r,mid+1,r,x,y)) mod mo; 45 end; 46 47 48 begin 49 // assign(input,'bzoj3939.in'); reset(input); 50 // assign(output,'bzoj3939.out'); rewrite(output); 51 readln(n,m,k); 52 for i:=1 to n do 53 for j:=1 to m do read(a[i,j]); 54 55 dp[1,1]:=1; 56 for i:=1 to m do sum[1,i]:=1; 57 update(root[a[1,1]],1,m,1,1); 58 59 for i:=2 to n do 60 begin 61 for j:=m downto 1 do 62 begin 63 s1:=sum[i-1,j-1]; 64 s2:=query(root[a[i,j]],1,m,1,j-1); 65 dp[i,j]:=((s1-s2) mod mo+mo) mod mo; 66 update(root[a[i,j]],1,m,j,dp[i,j]); 67 end; 68 for j:=1 to m do 69 begin 70 f[j]:=(f[j-1]+dp[i,j]) mod mo; 71 sum[i,j]:=(sum[i-1,j]+f[j]) mod mo; 72 end; 73 end; 74 writeln(dp[n,m]); 75 {for i:=1 to n do 76 begin 77 for j:=1 to m do write(dp[i,j],' '); 78 writeln; 79 end; } 80 81 82 close(input); 83 close(output); 84 end.
null