t1 Move Brackets:遍历括号串,遇到左括号计数器加1,遇到右括号时若有未匹配的左括号则匹配掉(计数器减1),否则这个右括号无法匹配,答案加1。最终答案就是需要移动的右括号数量。
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--){
int n;
string s;
cin>>n>>s;
int cnt=0,ans=0;
for(char c:s){
if(c=='(') cnt++;
else{
if(cnt>0) cnt--;
else ans++;
}
}
cout<<ans<<"\n";
}
return 0;
}
t2 And It's Non-Zero:在区间[l,r]中删掉最少的数使剩余数按位与非零,等价于找区间内某一位上1出现次数最多,保留这些数。预处理前缀和统计每位1的个数,枚举18位取区间内1的个数的最大值,答案即为区间长度减最大值。
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int pre[N][18];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
for(int i=1;i<N;i++){
for(int j=0;j<18;j++){
pre[i][j]=pre[i-1][j]+((i>>j)&1);
}
}
int T;
cin>>T;
while(T--){
int l,r;
cin>>l>>r;
int len=r-l+1;
int mx=0;
for(int j=0;j<18;j++){
int cnt=pre[r][j]-pre[l-1][j];
mx=max(mx,cnt);
}
cout<<len-mx<<"\n";
}
return 0;
}
t3 Iva & Pav:(这里决定换了码风)区间按位与值随右端点增大单调不增。用ST表预处理任意区间的按位与值,O(1)查询。对每个询问(l,k),若a[l]<k则无解输出-1;否则二分右端点r找最大的r使区间按位与≥k。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 200005;
int n, q;
int a[MAXN];
int lg[MAXN];
int st[MAXN][20];
void init() {
lg[1] = 0;
for (int i = 2; i < MAXN; i++) {
lg[i] = lg[i / 2] + 1;
}
}
void build() {
for (int i = 1; i <= n; i++) st[i][0] = a[i];
for (int j = 1; (1 << j) <= n; j++) {
for (int i = 1; i + (1 << j) - 1 <= n; i++) {
st[i][j] = st[i][j - 1] & st[i + (1 << (j - 1))][j - 1];
}
}
}
int query(int l, int r) {
int k = lg[r - l + 1];
return st[l][k] & st[r - (1 << k) + 1][k];
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
init();
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
build();
cin >> q;
while (q--) {
int l, k;
cin >> l >> k;
if (a[l] < k) {
cout << -1 << ' ';
continue;
}
int L = l, R = n, ans = l;
while (L <= R) {
int mid = (L + R) / 2;
if (query(l, mid) >= k) {
ans = mid;
L = mid + 1;
} else {
R = mid - 1;
}
}
cout << ans << ' ';
}
cout << '\n';
}
return 0;
}
t4 Number of Ways:先求前缀和,若总和不能被3整除则无解。目标和为sum/3。从前往后扫描,当当前位置前缀和等于目标和时计数加1,当等于两倍目标和时答案加上当前计数。
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n;
cin >> n;
vector<long long> a(n + 1), pref(n + 1, 0);
for (int i = 1; i <= n; i++) {
cin >> a[i];
pref[i] = pref[i - 1] + a[i];
}
long long sum = pref[n];
if (sum % 3 != 0) {
cout << 0 << '\n';
return 0;
}
long long tt = sum / 3;
long long cnt = 0, ans = 0;
for (int i = 1; i < n; i++) {
if (pref[i] == tt * 2) ans += cnt;
if (pref[i] == tt) cnt++;
}
cout << ans << '\n';
return 0;
}
t5 Xor-Subsequence:dp[i]表示以i结尾的最长合法子序列长度。转移时只需往前检查有限个位置,因为异或性质保证最优转移不会相隔太远。若满足(vec[i]^j) > (vec[j]^i)则更新dp。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> vec;
ll n;
int solve() {
cin >> n;
vec.resize(n);
for (auto& c : vec) cin >> c;
vector<ll> dp(1);
ll bst = 0;
for (int i = 0; i < n; i++) {
dp.push_back(1);
for (int j = i - 1; j >= max(0ll, i - 512); j--) {
if ((vec[i] ^ j) > (vec[j] ^ i)) {
dp.back() = max(dp.back(), dp[j + 1] + 1);
}
}
bst = max(bst, dp.back());
}
cout << bst << "\n";
return 0;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--) solve();
}
t6 Shuffling Songs:将每首歌看作图的节点,若两首歌的歌手或歌名相同则连边。问题转化为找最长路径,用状压DP:dp[mask][last]表示已选节点集合mask且最后一个是last的最长路径长度。答案删去最少歌曲数为n减去最长路径长度。
#include <bits/stdc++.h>
using namespace std;
int n, ans;
string g[20], w[20];
int mp[20][20];
int dp[1 << 16][16];
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while (T--) {
cin >> n;
for (int i = 0; i < n; i++) cin >> g[i] >> w[i];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
mp[i][j] = (g[i] == g[j] || w[i] == w[j]);
}
}
int full = 1 << n;
ans = 0;
for (int mask = 0; mask < full; mask++) {
for (int i = 0; i < n; i++) dp[mask][i] = -1e9;
}
for (int i = 0; i < n; i++) dp[1 << i][i] = 1;
for (int mask = 0; mask < full; mask++) {
for (int last = 0; last < n; last++) {
if (dp[mask][last] < 0) continue;
ans = max(ans, dp[mask][last]);
for (int nxt = 0; nxt < n; nxt++) {
if (mask & (1 << nxt)) continue;
if (!mp[last][nxt]) continue;
int nmask = mask | (1 << nxt);
dp[nmask][nxt] = max(dp[nmask][nxt], dp[mask][last] + 1);
}
}
}
cout << n - ans << '\n';
}
return 0;
}
评论
0