Codeforces Round #788 (Div. 2) Editorial
题意:判断交换正负号后序列能否变成非递减序列
思路:把所有负号都换到前面的数,然后判断此时序列是否满足题意
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1e5 + 10;
int n;
int a[N];
vector<int>inc, decc;
int pos, neg;
void solve()
{
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> a[i];
if (a[i] > 0) pos++;
else neg++;
}
for (int i = 0; i < n; i++)
{
if (neg > 0) {
if (a[i] > 0)
a[i] = - a[i];
neg--;
}
else if (neg == 0){
a[i] = abs(a[i]);
}
}
int flag = 1;
for (int i = 0; i < n - 1; i++)
{
if (a[i] > a[i + 1])
{
flag = 0;
break;
}
}
if (flag) puts("YES");
else puts("NO");
}
signed main(){
ios_base::sync_with_stdio(false), cin.tie(0);
int T; cin >> T;
while(T--) solve();
return 0;
}
思路:找相邻两个是特殊字母的距离。
用map
就很妙!
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1e5 + 10;
int n, k;
int sep[30];
string s;
void solve()
{
cin >> n >> s >> k;
map<char, int>mp;
for (int i = 0; i < k; i++)
{
char x;
cin >> x;
mp[x]++;
}
int l = 0, r = 0, ans = 0;
for (int i = 0; i < n; i++)
{
if (mp[s[i]])
{
l = r;
r = i;
ans = max(r - l, ans);
}
}
cout << ans << endl;
}
signed main(){
ios_base::sync_with_stdio(false), cin.tie(0);
int T; cin >> T;
while(T--) solve();
return 0;
}
知识点:并查集
题意:对于未确定的c[i]
,可以让其等于a[i]orb[i]
,问c
序列有几种可能。
对于c[i]
是已知的数,或c[i]
未知但a[i]==b[i]
,那么a[i],b[i]
序列对c
序列就没有贡献,因为此时c[i]
位置只有一种可能,否则就会对c
序列有两种方案数的贡献。
每个环对结果的贡献是 2 2 2,所以我们要找环的数量,什么是环呢?
环就是有关联的数组成的集合,环内的(这个集合内)的一个数字被确定,其他数字也就会固定只有一种选择了。所以答案是 2 环的个数 2^{环的个数} 2环的个数。
我的理解是这样的。。。
#include <bits/stdc++.h>
//#define int long long
#define endl '\n'
using namespace std;
const int N = 1e5 + 10, mod = 1e9 + 7;;
int n;
int p[N];
int a[N], b[N], c[N];
int find(int x)
{
if (p[x] != x) p[x] = find(p[x]);
return p[x];
}
void solve()
{
cin >> n;
int ans = 1;
for (int i = 1; i <= n; i++) cin >> a[i], p[i] = i;
for (int i = 1; i <= n; i++) cin >> b[i];
for (int i = 1; i <= n; i++)
{
int x;
cin >> x;
if (x == 0 && a[i] != b[i])
{
int pa = find(a[i]);
int pb = find(b[i]);
if (pa == pb)
{
ans *= 2;
ans %= mod;
}
else p[pa] = pb;
}
}
cout << ans << endl;
}
signed main(){
ios_base::sync_with_stdio(false), cin.tie(0);
int T; cin >> T;
while(T--) solve();
return 0;
}
题意:在图案上画线,问最少画几条线能形成指定数量的三角形。
我们可以发现,在这个图形上画线是有一定规律的。
综上所述:
我们连画带猜可以得出一个规律:
如果令数组inc[]
表示每次增加的三角形个数,我们可以发现:以三为一个周期。
令s[]
数组为三角形的总个数,那么s[i]=s[i-1]+inc[i]
。
我们要做的就是对数据预处理,最后二分查找对应个数。
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1e6 + 10;
int n;
int pre[N];
int inc[N];
int len;
void getpre()
{
len = 0;
while(pre[len] < 1e9)
{
len++;
if (len % 3 == 1) inc[len] = inc[len - 1];
else inc[len] = inc[len - 1] + 2;
pre[len] = pre[len - 1] + inc[len];
}
}
void solve()
{
cin >> n;
int pos = lower_bound(pre, pre + len + 1, n) - pre;//这里末尾位置是pre+len+1,但pre+len也能过
cout << pos << endl;
}
signed main(){
ios_base::sync_with_stdio(false), cin.tie(0);
int T; cin >> T;
getpre();
while(T--) solve();
return 0;
}