A
这个似乎出过一遍了?选一个偶数或者两个奇数。
B
题意:
给你
个数
再给你
个数
有一个矩形
的矩形C,
,且
中的数不是0,就是1,所以C中也是不是零就是1。
现在给你一个
,让你输出C中面积为
的矩形个数。
思路:
这个题目怎么说呢,说好想也好像,说不好想也不好想。。。。
首先,因为
中不是零就是1,所以C中为1的区域肯定是矩形,且大小为
中连续1的个数 *
中连续1的个数,有疑问可以画一下,到这儿还是比较好想的。然后接下来是重点。
假设a产生的连续的段为
b产生连续的段为
这可以构成
个矩形。
我们先按正解来,对于面积
的矩形,我们枚举边长,
然后提前预处理好
中段对x的贡献,每一个为
;同理
也是这样。
答案就是
。对于枚举边长,复杂度
,预处理时间复杂度也是
。
这样想似乎这个题目也就这样。。。。
但在比赛中我没想到直接枚举面积为 的矩形边长,而是枚举的 中可以产生的矩形,正如上文所说, 可以构成矩形为 个。对于每个矩形我们算面积为 的贡献,怎么算呢?对于每个矩形 ,也是枚举边长,不过是枚举 的边长,看其是否可以构成面积为 的矩形,这里假设枚举 的边长为 ,那么 。那么 可以产生 的贡献为 。其中 的范围 。我们不断累加贡献,也能得到贡献,但这样随机数据尚可,但最坏会被卡成 。值的一提的是我一开始看错范围以为4000。。。一直Wa和T,后经ZHJ提醒,数组开到40000,竟然以998ms的时间卡过,虽说后来重测被卡掉,但是这也不失是一件趣事。
赛后我以我的思路印证题解中代码,一直对上面正解中预处理边长累加那儿有疑惑,这很矛盾,在我的思路中,是枚举矩形然后对于这个矩形,在枚举边长,贡献是相乘后在相加,而题解中是相加后在相乘,这可能对别人来说很容易想透的,但对于我而言,这有点无法接受,人和人之间的思维方式真的有差别。
我按我的方式进行了思考,发现这两种思路是殊途同归的。我将用我的思路来解释正解。
假设
数组又连续段
,b数组有连续段
我们可以构造
x
,
x
,
x
,
x
,四个矩形,原来是对每个矩形枚举边会超时,现在是对面积为
的矩形我们找边
然后这四个矩形对其产生的贡献为
我们对上述式子进行提取公因式得
这个式子就是说对于边
结果是,a中所有段对
产生的贡献相加 乘以 b中所有段对
产生贡献的累加,这里所说的贡献可以当做产生多少
,产生多少
。
bool a[N],b[N];
ll q[N],p[N];
void init(int n,int m){
int cnt1(0),cnt2(0);
rep(i,1,n){
if(a[i] == 0){
for(int j =1 ;j <= cnt1;++j){
q[j] += cnt1 - j + 1;
}
cnt1 = 0;
}
else cnt1 ++;
}
if(cnt1){
rep(j,1,cnt1) q[j] += cnt1 - j + 1;
}
rep(i,1,m){
if(b[i] == 0) {
for(int j = 1;j <= cnt2;++j) p[j] += cnt2 - j + 1;
cnt2 = 0;
}
else cnt2++;
}
if(cnt2){
rep(j,1,cnt2) p[j] += cnt2 - j + 1;
}
}
int main(){
int n = read(),m = read(),k =read();
rep(i,1,n) a[i] = read();
rep(i,1,m) b[i] = read();
init(n,m);
ll ans = 0;
for(int i = 1;i <= n;++i){
if(k % i == 0){
int x = i,y = k/i;
if(y <= m) ans += q[x]*p[y];
}
}
cout<< ans;
}
C
题意:
就是括号匹配,但是现在的问题是你可以通过对任意
排序,代价是这段的长度,来使的括号匹配。
思路:
首先就是若左右括号不等则一定不能匹配,否则一定可以。
我们设一个栈,然后从头遍历每个字符。
我们知道括号匹配的形式是
,所以我们考虑当前字符是否是’(’,如果是的话,看栈顶元素是否是’)’,如果是的话,这说明可以将这两个字符排序可以正确匹配,所以我们将
,并且删除栈顶元素;不是的话就将’(‘入栈。
如果当前元素是’)’ ,看栈顶是否是’('是的话就删除栈顶元素;否则入栈。
我们发现这样的匹配思路并没有错,而且代码还很好写。具体的怎么的正确我曾尝试证明,但是失败了。
stack<char> st;
int main(){
int n = read();
string s;
cin >> s;
int l = s.size();
int cnt1(0),cnt2(0);
rep(i,0,l-1){
if(s[i]=='(') cnt1++;
else cnt2++;
}
if(cnt1!=cnt2) return puts("-1"),0;
int ans = 0;
rep(i,0,l-1){
if(s[i] =='('){
if(st.size()&&st.top()==')'){st.pop();ans+=2;}
else st.push('(');
}
else if(st.size()&&st.top()=='(') st.pop();
else st.push(s[i]);
}
cout <<ans;
}
D