Most Dangerous Shark

64 篇文章 0 订阅
3 篇文章 0 订阅

Description

Semyon participates in the most prestigious competition of the world ocean for the title of the most dangerous shark. During this competition sharks compete in different subjects: speed swimming, masking, map navigation and many others. Now Semyon is taking part in «destruction» contest.

During it, mm dominoes are placed in front of the shark. All dominoes are on the same line, but the height of the dominoes may vary. The distance between adjacent dominoes is 11. Moreover, each Domino has its own cost value, expressed as an integer. The goal is to drop all the dominoes. To do this, the shark can push any domino to the left or to the right, and it will begin falling in this direction. If during the fall the domino touches other dominoes, they will also start falling in the same direction in which the original domino is falling, thus beginning a chain reaction, as a result of which many dominoes can fall. A falling domino touches another one, if and only if the distance between them was strictly less than the height of the falling domino, the dominoes do not necessarily have to be adjacent.

Of course, any shark can easily drop all the dominoes in this way, so the goal is not to drop all the dominoes, but do it with a minimum cost. The cost of the destruction is the sum of the costs of dominoes that the shark needs to push to make all the dominoes fall.

Simon has already won in the previous subjects, but is not smart enough to win in this one. Help Semyon and determine the minimum total cost of the dominoes he will have to push to make all the dominoes fall.

Input

In order to reduce input size, the heights and costs of the dominoes are described with blocks.

The first line contains two integers nn and mm (1≤n≤250000,1≤m≤1071≤n≤250000,1≤m≤107) — the number of the blocks and the total number of the dominoes Semyon must drop.

Then descriptions of nn blocks follow. Description of every block consists of three lines.

The first line of block's description contains a single integer kiki (1≤ki≤250000,∑ni=1ki≤2500001≤ki≤250000,∑i=1nki≤250000) — the number of dominoes in the block.

The second line of block's description contains kiki integers ajaj (1≤aj≤m1≤aj≤m) — the heights of the dominoes in the blocks.

The third line contains kiki integers cjcj (1≤cj≤1000001≤cj≤100000) — the costs of the dominoes in the block.

Then the domino sequence is described (from left to right).

The first line of this description contains a single integer qq (n≤q≤250000n≤q≤250000) — the number of blocks in the sequence of domino sequence.

Each of the following qq lines contains integers idi,muliidi,muli (1≤idi≤n1≤idi≤n, 1≤muli≤1000001≤muli≤100000), denoting that the next kidikidi dominoes are dominoes of the block idiidi, with their cost multiplied by mulimuli.

It's guaranteed, that ∑qi=1kidi=m∑i=1qkidi=m, and that's every block is used in the sequence at least once.

Output

Print exactly one integer — the minimum cost to make all the dominoes fall.

Examples

input

Copy

2 7
3
1 2 2
1 2 1
1
3
2
3
2 2
1 3
1 1

output

Copy

5

input

Copy

1 1
1
1
100000
1
1 100000

output

Copy

10000000000

Note

In the first example, there are 77 dominoes in front of the Semyon. Their heights are equal to [3,1,2,2,1,2,2][3,1,2,2,1,2,2], and their costs are equal to [4,3,6,3,1,2,1][4,3,6,3,1,2,1]. Semyon should drop the domino with index 77 to the left, it will fall and drop the domino 66 as well. The domino 66 during the fall will drop the domino 55, however the latter will not drop any more dominoes. Then Semyon should drop domino with number 11 to the right and it will drop dominoes 22 and 33 after falling. And the domino 33 will drop the domino 44 after falling. Hence all dominoes are fallen this way.

In the second example, there is a single domino of cost 1000000000010000000000.

Solution

先用栈预处理出l[i] r[i]分别表示i往左推倒的最左能推到的点,往右倒能推到的点。

首先发现 i 能推到的最左边的点 至少是 i-h[ i ]+1能推到的最左边的点(甚至可能再左),因此我们发现l[ i ]是每次只需要找出 i-h[ i ]+1~i这一段范围内的 l[ j ]的最小值。

并且当处理完这个点后,i-h[ i ]+1~i-1 的这些点一定是没有用的,因为 l[ i ]一定都会小于等于这其中所有点的 l[ j ],那么就将这个范围内的在栈中的点用来更新l[ i ]的同时将其弹出。

最后再将当前位置的 l[ i ] 加入到栈中。

对于r[ i ]同理。

接下来就是dp了。

设f[ i ]表示推完了前i个点,其中第i个点往左被推倒(自身被推倒而不是被其他点推倒)

设g[ i ]表示推倒了前i个点,其中第i个点被往右推倒了(可能是自身被推倒也有可能是被其他点推倒)

那么f[i]=min(f[l[i]-1],g[l[i]-1])+cost[i],可以从前l[ i ]-1都被推倒了(怎么推倒都行)转移过来。

对于g[],第一种情况是自身被推倒而不是被别人推倒,那么有:

g[i]=min(f[i-1],g[i-1])+cost[i]

第二种情况,是被别人推倒,那么有:
g[i]=g[j]~ ~(j<i~~and~~r[j]>=i )

对于这个的维护可以维护一个栈,栈中的每一个点可以推倒栈中的下一个点。

每次找到栈顶的一个能够推倒i个一个点,不能推倒就弹栈。

这时就用栈顶的g更新当前g。

再判断如果当前g比栈顶的点的g值小就入栈,以保证g是单调递减的,也就是栈顶是最优解。

 

Code

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#define I int
#define ll long long
#define F(i,a,b) for(I i=a;i<=b;i++)
#define Fd(i,a,b) for(I i=a;i>=b;i--)
#define mem(a,b) memset(a,b,sizeof a)
#define N 10000004
using namespace std;
I n,m,id,p,k[N],b[N],a[N],h[N],l[N],r[N],st[N],ind[N],mul[N],tp,tot;
ll f[N],g[N],c[N];
char ch;
void R(I &x){
	x=0;I w=1;ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	x*=w;
}
I main(){
//	freopen("Most Dangerous Shark.in","r",stdin);
//	freopen("Most Dangerous Shark.out","w",stdout);
	R(m),R(n);
	F(i,1,m){
		R(k[i]);k[i]+=k[i-1];
		F(j,k[i-1]+1,k[i]) R(a[j]);
		F(j,k[i-1]+1,k[i]) R(b[j]);
	}
	R(m);
	F(j,1,m){
		R(id),R(p);
		ind[j]=id,mul[j]=p;
		F(i,k[id-1]+1,k[id]){
			++tot;
			h[tot]=a[i],c[tot]=(ll)b[i]*p;
		}
	}
	tp=0;
	F(i,1,tot){
		l[i]=max(1,i-h[i]+1);
		while(tp&&i-st[tp]+1<=h[i]){l[i]=min(l[i],l[st[tp--]]);}
		st[++tp]=i;
	}
	tp=0;
	Fd(i,tot,1){
		r[i]=min(tot,i+h[i]-1);
		while(tp&&st[tp]-i+1<=h[i]){r[i]=max(r[i],r[st[tp--]]);}
		st[++tp]=i;
	}
	f[0]=g[0]=tp=0;
	F(i,1,tot){
		f[i]=min(f[l[i]-1],g[l[i]-1])+c[i];
		g[i]=min(f[i-1],g[i-1])+c[i];
		while(tp&&r[st[tp]]<i) tp--;
		if(tp) g[i]=min(g[i],g[st[tp]]);
		if(!tp||g[i]<g[st[tp]]) st[++tp]=i;
	}
	printf("%lld\n",min(f[tot],g[tot]));
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值