好久没来论坛了,WA30有大佬看看吗

3.  风蚀
题目ID:24476必做题文件操作100分

订正得分

赛中得分
最新提交:
Wrong Answer
30 分
历史最高:
Wrong Answer
30 分
时间限制: 2000ms
空间限制: 524288kB
输入文件名: wind.in
输出文件名: wind.out
题目描述
考古队发现了一排古老的岩柱,一共有 
n
n 根,从左到右编号为 
1
1 到 
n
n。

第 
i
i 根岩柱有一个坚硬度 
a
i
a 
i
​
 。保证所有坚硬度 两两不同。

考古队会对一段连续岩柱做“风蚀实验”。

设这一段是从第 
l
l 根到第 
r
r 根。实验按“天”进行。

第 1 天,这一整段岩柱看成一个完整的连续块。

之后每一天的操作会对当前所有连续块分别进行同样的操作,彼此互不影响:

在这个连续块里,找出坚硬度最小的那一根岩柱;
这根岩柱会在这一天被风蚀掉;
记下一个二元组 
(
L
,
R
)
(L,R),其中:
L
L 表示这根岩柱左边、仍属于这个连续块的岩柱数量;
R
R 表示这根岩柱右边、仍属于这个连续块的岩柱数量。
因为所有坚硬度两两不同,所以每个连续块里“最小的那根岩柱”总是唯一的。

把这一天所有连续块得到的二元组,按照这些连续块从左到右的顺序依次写下来,就得到这一天的 风蚀记录。

当天结束后,被风蚀掉的岩柱消失。剩下的岩柱会分裂成若干个新的连续块,进入下一天。

如果某一天开始时已经没有岩柱了,那么这一天以及之后所有天的风蚀记录都视为空序列。

现在有 
q
q 次询问。

每次询问给出两段连续区间 
[
l
1
,
r
1
]
[l 
1
​
 ,r 
1
​
 ] 和 
[
l
2
,
r
2
]
[l 
2
​
 ,r 
2
​
 ]。

如果这两段区间在 每一天 得到的风蚀记录都完全相同,就称它们是 同谱 的。

你需要对每次询问回答这两段区间是否同谱。

输入格式
第一行两个整数 
n
,
q
n,q。

第二行 
n
n 个整数 
a
1
,
a
2
,
…
,
a
n
a 
1
​
 ,a 
2
​
 ,…,a 
n
​
 ,表示每根岩柱的坚硬度。保证它们两两不同。

接下来 
q
q 行,每行四个整数 
l
1
,
r
1
,
l
2
,
r
2
l 
1
​
 ,r 
1
​
 ,l 
2
​
 ,r 
2
​
 ,表示一次询问。

输出格式
对于每次询问输出一行。

如果两段区间同谱,输出 Yes;否则输出 No。

样例
Input 1
7 5
3 1 4 2 7 5 6
1 3 5 7
1 4 4 7
2 4 5 7
1 1 4 4
3 6 4 7
Output 1
Yes
No
No
Yes
No
样例解释
区间 
[
1
,
3
]
[1,3] 的序列是 
(
3
,
1
,
4
)
(3,1,4),区间 
[
5
,
7
]
[5,7] 的序列是 
(
7
,
5
,
6
)
(7,5,6)。它们第一天都会删掉中间位置的最小值,得到记录 
(
1
,
1
)
(1,1);第二天左右各剩一个单点块,记录也完全一样,所以它们同谱。
区间 
[
1
,
4
]
[1,4] 和 
[
4
,
7
]
[4,7] 第一天删掉最小值后,左右剩余规模就不同,因此不同谱。
数据范围
对于所有测试数据,均有:

1
≤
n
,
q
≤
5
×
1
0
5
1≤n,q≤5×10 
5
 ;
对于所有 
1
≤
i
≤
n
1≤i≤n,均有 
1
≤
a
i
≤
n
1≤a 
i
​
 ≤n,且 
a
1
,
a
2
,
…
,
a
n
a 
1
​
 ,a 
2
​
 ,…,a 
n
​
  两两不同;
对于所有询问,均有 
1
≤
l
1
≤
r
1
≤
n
,
 
1
≤
l
2
≤
r
2
≤
n
1≤l 
1
​
 ≤r 
1
​
 ≤n, 1≤l 
2
​
 ≤r 
2
​
 ≤n。
测试点编号	
n
≤
n≤	
q
≤
q≤	特殊性质
1	500	500	无
2	2000	2000	无
3	3000	3000	无
4,5	50000	50000	A
6	100000	100000	B
7	100000	100000	C
8	100000	100000	D
10	100000	100000	E
9,11	200000	100000	无
12	200000	100000	D
13,14	300000	200000	无
15,16	300000	200000	D
17 - 20	500000	500000	无
特殊性质 A:对于所有询问,均有 
r
1
−
l
1
+
1
≤
32
r 
1
​
 −l 
1
​
 +1≤32 且 
r
2
−
l
2
+
1
≤
32
r 
2
​
 −l 
2
​
 +1≤32。

特殊性质 B:数组严格递增,即对于所有 
1
≤
i
≤
n
1≤i≤n,均有 
a
i
=
i
a 
i
​
 =i。

特殊性质 C:数组严格递减,即对于所有 
1
≤
i
≤
n
1≤i≤n,均有 
a
i
=
n
−
i
+
1
a 
i
​
 =n−i+1。

特殊性质 D:数组为交错排列,即

a
=
(
1
,
n
,
2
,
n
−
1
,
3
,
n
−
2
,
…
 
)
.
a=(1,n,2,n−1,3,n−2,…).
特殊性质 E:对于所有询问,均有 
l
1
=
l
2
=
1
l 
1
​
 =l 
2
​
 =1。

附件
#include<bits/stdc++.h>
#define int long long
using namespace std;

const int N = 5e5+5;
const int mod = 1e9+7;
int n,q,a[N],pre[N],check[N];
int h[N],top,num;
const int B = 223;
vector<int> vis[N];
int c[N],ans[2*N],power[N];
struct node{
	int l,r,id;
}s[2*N];
map<int,int> mp;

inline int lowbit(int o){
	return o & -o;
}

void add(int a,int w){
	int i = a;
	while(i<=n){
//		cout<<i<<endl; 
		c[i] = (c[i]+w)%mod;
		i += lowbit(i);
	}
	return ;
}
int query(int a){
	int res = 0;
	int i = a;
	while(i>0){
		res = (res+c[i])%mod;
		i -= lowbit(i);
	}
	return res;
}

void init(){
	power[0] = 1;
	for(int i = 1; i<=n; i++){
		power[i] = (power[i-1]*B)%mod;
	}
//	cout<<power[1]<<endl;
	return ;
}

int quick(int a,int b){
	int res = 1;
	while(b>0){
		if(b & 1) res=(res*a)%mod;
		a = (a*a)%mod;
		b >>= 1;
	}
	return res;
}

bool cmp(node a,node b){
	return a.l>b.l;
}

signed main(){
	freopen("wind.in","r",stdin);
	freopen("wind.out","w",stdout);
	cin>>n>>q;
	init();
	for(int i = 1; i<=n; i++){
		cin>>a[i];
	}
//	cout<<1<<endl;
	for(int i = 1; i<=n; i++){
		while(top>0 && a[h[top]]>=a[i]) top--;
		pre[i] = h[top];
		top++;
		vis[pre[i]].push_back(i);
//		cout<<pre[i]<<' '; 
		h[top] = i;
	}
	cout<<endl;
	for(int i = 1; i<=q; i++){
		int l1,l2,r1,r2;
		cin>>l1>>r1>>l2>>r2;
		s[i*2-1].l=l1,s[i*2-1].r=r1,s[i*2].l=l2,s[i*2].r=r2;
//		s[i*2-1].pos = i*2;
		s[i*2-1].id=s[i*2].id=i;
		check[i] = -1;
	}
//	cout<<1<<endl;
	sort(s+1,s+2*q+1,cmp);
	num = 1;
	for(int i = n; i>=1; i--){
//		cout<<"111 "<<i<<endl; 
		for(int j = 0; j<vis[i].size(); j++){
//			cout<<vis[i][j]<<' ';
			add(vis[i][j],(vis[i][j]-i)*power[vis[i][j]]%mod);
//			cout<<vis[i][j]<<" "<<(vis[i][j]-i)*power[vis[i][j]]%mod<<endl; 
		}
//		cout<<22<<endl;
		while(s[num].l == i){
			int l=s[num].l,r=s[num].r;
			ans[num] = (query(r)-query(l-1)+mod)%mod*quick(quick(B,l),mod-2)%mod;
//			cout<<endl;
//			cout<<l<<" "<<r<<endl;
//			cout<<query(r)<<' '<<query(l-1)<<endl;
//			cout<<ans[num]<<endl;
			num++;
		}
//		cout<<endl;
	}
	
	for(int i = 1; i<=2*q; i++){
//		cout<<"111 "<<s[i].id<<endl;
		if(check[s[i].id] == -1){ 
			check[s[i].id] = ans[i];
		}else{
//			cout<<s[i].id<<endl; 
			if(check[s[i].id] == ans[i]) check[s[i].id]=1;
			else check[s[i].id]=0;
		}
	}
	for(int i = 1; i<=q; i++){
		if(check[i]) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
} 

完了,一看打字框发现不太会用了

题目截图一下呗



此话题已在最后回复的 15 天后被自动关闭。不再允许新回复。