A. Remove a Progression
分析:找找规律就可以了。
#include "bits/stdc++.h"
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
int n,x;
cin>>n>>x;
cout<<2*x<<endl;
}
}
B. Yet Another Crosses Problem
分析:记录每行和每列分别有几个,然后枚举行列记录一下最小值就可以了。注意如果枚举的点有的话要减1.
#include "bits/stdc++.h"
using namespace std;
int r[50004],c[50004];
set<int>se[50004];
int main(){
int q;
cin>>q;
while(q--){
int n,m;
scanf("%d%d",&n,&m);
for (int i = 0; i <= n; ++i) {
r[i]=0;
se[i].clear();
}
for (int i = 0; i <= m; ++i) {
c[i]=0;
}
scanf("%d%d",&n,&m);
string s;
for (int i = 1; i <= n; ++i) {
cin>>s;
int sum = 0;
for (int j = 0; j < s.length(); ++j) {
if(s[j]=='*'){
se[i].insert(j+1);
c[j+1]++;
sum++;
}
}
r[i]=sum;
}
int ans = 1e9;
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
int cnt = 0;
if(se[i].count(j))cnt++;
ans = min(ans,n+m-1 - r[i] - c[j] + cnt);
}
}
printf("%d\n",ans);
}
}
C. From S To T
分析:双下标模拟跑一下就可以了。
#include "bits/stdc++.h"
using namespace std;
int r[50004],c[50004];
set<int>se[50004];
int main(){
int q;
cin>>q;
while(q--) {
string s,t,q;
cin>>s>>t>>q;
int pos = 0;
for (int i = 0; i < t.size() && pos < s.size(); ++i) {
if(s[pos]==t[i]){
pos++;
t.erase(t.begin()+i);
i--;
}
}
if(pos != s.size())puts("NO");
else {
sort(t.begin(),t.end());
sort(q.begin(),q.end());
pos = 0 ;
for (int i = 0; i < q.size() && pos < t.size(); ++i) {
if(q[i]==t[pos]){
pos++;
}
}
if(pos==t.size())puts("YES");
else puts("NO");
}
}
}
D. 1-2-K Game
分析:写个SG或者手推一下就可以发现规律。当k%3!=0时是不会改变状态的,故只需要判断n%3就可以了。
当k%3==0时是可以影响的,容易发现循环节长度是k+1,推一下结论就可以了,详见代码。
#include "bits/stdc++.h"
using namespace std;
int r[50004],c[50004];
set<int>se[50004];
int main(){
int t;
cin>>t;
while(t--){
int n,k;
cin>>n>>k;
if(k%3!=0){
if(n%3==0)puts("Bob");
else puts("Alice");
}
else {
int x = n%(k+1);
if(x%3==0&&x!=k)puts("Bob");
else if(x==k+1)puts("Bob");
else puts("Alice");
}
}
}
E. Count The Rectangles
分析:暴力枚举,简单优化一下枚举竖着两条边,然后找有多少条横着的同时与这两条边相交。
那么可以在找与这两条边相交的横着的线上优化。
当我们枚举到左边的边,就可以确定一个横着的边的集合,要求这个集合里的边的左端点要<=这条左边的边的x值。
可以处理出这个集合。
然后在枚举第二条边的时候,我们按照横坐标从大到小枚举,显而易见的是若在集合中的某条边与靠右的相交了,那么也一定和靠左的也相交,那么我们就可以用bit来维护一下,将集合中的边排序后根据第二个枚举边的值依次加入,然后计数就可以了。
复杂度。
#include "bits/stdc++.h"
using namespace std;
const int mod = 1e9 + 7;
struct BIT {
int n;
vector<long long> v;
BIT(int n) : n(n) { v.resize(n + 1); }
void update(long long x, long long d) {
while (x <= n) {
v[x] += d;/*if (v[x] >= mod)v[x] -= mod*/;
x += (x & -x);
}
}
long long que(long long x) {
long long res = 0;
while (x > 0) {
res += v[x];/*if (res >= mod)res -= mod*/;
x -= (x & -x);
}
return res;
}
};
struct node {
int x, y, z;
bool friend operator<(node a, node b) {
return a.x < b.x;
}
};
struct xxx {
int first, second;
bool friend operator<(xxx a, xxx b) {
return a.first > b.first;
}
bool friend operator==(xxx a, xxx b) {
return a.first == b.first;
}
};
BIT bit(10004);
vector<node> a, b;//a shu
bool cmp(node a, node b) {
return a.z < b.z;
}
bool cmp1(node a, node b) {
return a.x < b.x;
}
int main() {
int n;
cin >> n;
int x1, x2, y1, y2;
for (int i = 0; i < n; ++i) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (x1 == x2)a.push_back({min(y1, y2), max(y1, y2), x1});
else b.push_back({min(x1, x2), max(x1, x2), y1});
}
sort(a.begin(), a.end(), cmp);
sort(b.begin(), b.end(), cmp1);
long long ans = 0;
for (int i = 0; i < a.size(); ++i) {
multiset<xxx> ms;
for (int j = 0; j < 10004; ++j) {
bit.v[j] = 0;
}
//bit.v.resize(10004,0);
for (int j = 0; j < b.size(); ++j) {
if (b[j].x <= a[i].z)ms.insert({b[j].y, b[j].z});
}
for (int j = a.size() - 1; j > i; --j) {
int up = min(a[i].y, a[j].y);
int dw = max(a[i].x, a[j].x);
while (ms.size() && ms.begin()->first >= a[j].z) {
bit.update(ms.begin()->second + 5002, 1);
ms.erase(ms.begin());
}
if (up <= dw)continue;
long long temp = bit.que(up + 5002);
temp -= bit.que(dw + 5001);
ans += temp * (temp - 1) / 2;
}
}
cout << ans << endl;
}