【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.

 

 

posted on 2017-02-21 14:58  myx12345  阅读(312)  评论(0编辑  收藏  举报

导航