1.变化的举行矩形
签到题,直接用cout会输出1e6之类的,用printf或者cout<<fixed<<setprecision(6)
2.吃鸡梦之队
枚举加二分查找
#include<iostream>
#include<cstring>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<vector>
using namespace std;
const int N=1e5+5;
int p1[N], p2[N];
int main() {
int t;
scanf("%d",&t);
while (t--) {
set<int> s1,s2, s3, s4;
int n;
scanf("%d",&n);
for (int i = 0; i < n; i++) {
scanf("%d",&p1[i]);
}
for (int i = 0; i < n; i++) {
scanf("%d", &p2[i]);
}
for (int i = 0; i < n; i++) {
if (p1[i] == 1) {
s1.insert(p2[i]);
}
else if (p1[i] == 2) {
s2.insert(p2[i]);
}
else if (p1[i] == 3) {
s3.insert(p2[i]);
}
else {
s4.insert(p2[i]);
}
}
int ans=1e9;
for (int i1 : s1) { //s1大s2小
auto it = s2.upper_bound(i1);
if (it == s2.begin()) {
continue;
}
it--;
int i2 = *it;
//s3小s4大
auto it4 = s4.lower_bound((i1+i2)/2);
if (it4 != s4.end()) {
int i4 = *it4;
auto it3 = s3.upper_bound(i4);
if (it3 != s3.begin()) {
it3--;
int i3 = *it3;
ans=min(ans, max(i1 - i3, i4-i2));
}
}
auto it3 = s3.upper_bound((i1 + i2) / 2);
if (it3 != s3.begin()) {
it3 -- ;
int i3 = *it3;
auto it4 = s4.lower_bound(i3);
if (it4 != s4.end()) {
int i4 = *it4;
ans = min(ans, max(i1 - i3, i4 - i2));
}
}
//s3大s4小
it3 = s3.lower_bound((i1 + i2) / 2);
if (it3 != s3.end()) {
int i3 = *it3;
auto it4 = s4.upper_bound(i3);
if (it4 != s4.begin()) {
it4--;
int i4 = *it4;
ans = min(ans, max(i1 - i4, i3 - i2));
}
}
it4 = s4.upper_bound((i1 + i2) / 2);
if (it4 != s4.begin()) {
it4--;
int i4 = *it4;
auto it3 = s3.lower_bound(i4);
if (it3 != s3.end()) {
int i3 = *it3;
ans = min(ans, max(i1 - i4, i3 - i2));
}
}
}
for (int i2 : s2) { //s1小s2大
auto it = s1.upper_bound(i2);
if (it == s1.begin()) {
continue;
}
it--;
int i1 = *it;
//s3小s4大
auto it4 = s4.lower_bound((i1 + i2) / 2);
if (it4 != s4.end()) {
int i4 = *it4;
auto it3 = s3.upper_bound(i4);
if (it3 != s3.begin()) {
it3--;
int i3 = *it3;
ans = min(ans, max(i2 - i3, i4 - i1));
}
}
auto it3 = s3.upper_bound((i1 + i2) / 2);
if (it3 != s3.begin()) {
it3--;
int i3 = *it3;
auto it4 = s4.lower_bound(i3);
if (it4 != s4.end()) {
int i4 = *it4;
ans = min(ans, max(i2 - i3, i4 - i1));
}
}
//s3大s4小
it3 = s3.lower_bound((i1 + i2) / 2);
if (it3 != s3.end()) {
int i3 = *it3;
auto it4 = s4.upper_bound(i3);
if (it4 != s4.begin()) {
it4--;
int i4 = *it4;
ans = min(ans, max(i2 - i4, i3 - i1));
}
}
it4 = s4.upper_bound((i1 + i2) / 2);
if (it4 != s4.begin()) {
it4--;
int i4 = *it4;
auto it3 = s3.lower_bound(i4);
if (it3 != s3.end()) {
int i3 = *it3;
ans = min(ans, max(i2 - i4, i3 - i1));
}
}
}
printf("%d\n", ans);
}
}
3.洞穴探险
比赛没做出来,先进行并查集缩点(因为是无向图,有向图是targan),建立超级源节点,是环的节点值设置为1否则为0,再进行倍增,求每个路径值,查询过程先并查集判断是否处于同一图中,不属于同一图中直接输出,属于同一图中再求ab之间路径长度是否大于1(使用lca算法),大于1说明经过缩点存在多条路径。
4.火柴棒等式
枚举所有合法的等式并记录状态,每个数字可以用7位bit表示,所以等式可以用int表示
#include<iostream>
#include<cstring>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<vector>
using namespace std;
const int N=1e3+5;
unordered_map<int,vector<int>> eq;
//unordered_set<int> num[7];
int num[10];
int cnt[10];
unordered_set<int> num_no[7];
int main() {
num_no[0].insert(1), num_no[0].insert(4);
num_no[1].insert(5), num_no[1].insert(6);
num_no[2].insert(2);
num_no[3].insert(1), num_no[3].insert(4),num_no[3].insert(7);
num_no[4].insert(1), num_no[4].insert(3),num_no[4].insert(4),num_no[4].insert(5),num_no[4].insert(7), num_no[4].insert(9); //134579
num_no[5].insert(1), num_no[5].insert(2),num_no[5].insert(3), num_no[5].insert(7);//1237
num_no[6].insert(0), num_no[6].insert(1), num_no[6].insert(7);//017
for (int i = 0; i < 10; i++) {
int s = 0;
int ct=0;
for (int j = 0; j < 7; j++) {
if (!num_no[j].count(i)) {
s |= 1<<j;
ct++;
}
}
cnt[i] = ct;
num[i] = s;
}
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 2; j++) {//+-
if(j==0){//-
for (int k = 0; k <= i; k++) {
int r = i - k;
int sum = cnt[i] + 1 + cnt[k] + cnt[r];
eq[sum].push_back((num[i]<<16)|(1<<14)|(num[k]<<7)|num[r]);
}
}
else {//+
for (int k = 0; k < 10 - i; k++) {
int r = i + k;
int sum = cnt[i] + 2 + cnt[k] + cnt[r];
eq[sum].push_back((num[i] << 16) | (3 << 14) | (num[k] << 7) | num[r]);
}
}
}
}
int t;
scanf("%d",&t);
while (t--) {
getchar();
char x,y,z,op;
scanf("%c %c %c = %c",&x,&op,&y,&z);
int x1 = x-'0', y1 = y-'0', z1 = z-'0';
int sum = cnt[x1]+cnt[y1]+cnt[z1]+(op=='+'?2:1);
int ans=1e9;
int s1 = (num[x1]<<16)|(op == '+' ? 3<<14 : 1<<14)|(num[y1]<<7)|num[z1];
if (eq[sum].empty()) {
printf("-1\n");
}
else {
for (int s : eq[sum]) {
int ct=0;
for (int i = 24; i >= 0; i--) {
ct += (((s>>i)&1) != ((s1>>i)&1));
}
ans=min(ans, ct);
}
printf("%d\n",ans/2);
}
}
}
6.排列
#include<iostream>
#include<cstring>
#include<set>
using namespace std;
int main() {
int t;
scanf("%d",&t);
while (t--) {
long long n;
scanf("%lld",&n);
if (n == 1) {
printf("0\n");
continue;
}
if (!(n & 1)) {
long long ans = (n / 2 + 1 + n) * (1 + n - (n / 2 + 1)) - (n / 2 + 1 )*(n / 2) - 1;
printf("%lld\n", ans);
}
else {
long long ans = (n/2+1+n)*(1+n-(n/2+1))-(n/2+1+n/2+2)-(1+n/2)*(n/2);
printf("%lld\n", ans);
}
}
}
7.数组查询
二分
#include<iostream>
#include<cstring>
#include<set>
using namespace std;
const int N=1e5+5;
int arr[N];
int main() {
int t;
scanf("%d",&t);
while (t--) {
int n;
scanf("%d",&n);
for (int i = 0; i < n; i++) {
scanf("%d",&arr[i]);
}
set<int> s;
int op ;
for (int i = 0; i < n; i++) {
s.insert(arr[i]);
scanf("%d",&op);
auto it = s.upper_bound(op);
if (it == s.begin()) {
printf("%d\n", -1);
}
else {
it--;
printf("%d\n", * it);
}
}
}
}
8.新冠病毒
#include<iostream>
using namespace std;
int main() {
int n;
cin>>n;
cout<<(long long)n*(n+1)/2<<endl<<(n+1)/2<<endl;
}
9.有星星就表白
先判断是否是树,再求最大节点度数,最大节点度数小于等于2或者度数大于2的节点个数为1则表白
#include<iostream>
#include<cstring>
#include<set>
using namespace std;
const int N=1e5+5;
int d[N];
int cnt=1;
int h[N], e[N<<1], nx[N<<1];
void add(int a, int b) {
e[cnt] =b, nx[cnt] = h[a], h[a] = cnt++;
}
int main() {
int t;
scanf("%d",&t);
while (t--) {
memset(d,0,sizeof d);
int n,m;
scanf("%d%d",&n,&m);
int x,y;
bool f = true;
if (n != m + 1) {
f=false;
}
int cnt=0;
for (int i = 0; i < m; i++) {
scanf("%d%d", &x,&y);
d[x]++, d[y]++;
//add(x, y);
//add(y, x);
}
if (!f) {
cout << "No\n";
}
else {
int md = 0;
for (int i = 1; i <= n; i++) {
md = max(md, d[i]);
}
if (md <= 2) {
cout<<"Yes\n";
}
else {
int cnt=0;
for (int i = 1; i <= n; i++) {
if (d[i] >= 3) {
cnt++;
}
}
if (cnt > 1) {
cout<<"No\n";
}
else {
cout<<"Yes\n";
}
}
}
}
}
10.笑声比赛
求最后一个xy前面的不同字符串数目,dp[i][j]表示前i个字符有长度为j的不同字符串数目
用last记录上一个arr[i]位置,如果last[arr[i]] = -1, 则dp[i][j] = dp[i-1][j] + dp[i-1][j-1],
否则dp[i][j] = dp[i-1][j] + dp[i-1][j-1]-dp[last[arr[i]] - 1][j-1]
#include<iostream>
#include<cstring>
#include<set>
#include<unordered_map>
#include<vector>
using namespace std;
const int N=1e3+5;
long long dp[N][N];
int mod=1e9+7;
int last[26];
char arr[N];
int main() {
int t;
scanf("%d",&t);
while (t--) {
memset(dp,0,sizeof dp);
memset(last,-1,sizeof last);
int n;
scanf("%d",&n);
/*string s;
cin>>s;*/
getchar();
for (int i = 0; i < n; i++) {
scanf("%c", &arr[i]);
}
dp[0][0] = 1;
for (int i = 1; i <= n; i++) {
dp[i][0] = 1;
for (int j = 1; j <= i; j++) {
//dp[i][j] = dp[i][j-1];
if(last[arr[i-1] - 'a'] != -1)
dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1] - dp[last[arr[i - 1] - 'a'] - 1][j - 1] + mod) % mod;
else {
dp[i][j] = (dp[i - 1][j] + dp[i - 1][j - 1]) % mod;
}
}
last[arr[i - 1] - 'a'] = i;
}
int q;
scanf("%d",&q);
unordered_map<char,int> mp;
unordered_map<char, set<int>> ms;
unordered_map<char, vector<int>> mv;
for (int i = 1; i <= n; i++) {
mp[arr[i-1]] = i;
ms[arr[i-1]].insert(i);
mv[arr[i-1]].push_back(i);
}
while (q--) {
char x,y;
int L;
getchar();
scanf("%c %c %d",&x,&y,&L);
//cin>>x>>y>>L;
if (!mp.count(x) || !mp.count(y)) {
printf("0\n");
}
else {
if (x == y) {
if (mv[x].size() < 2) {
printf("0\n");
}
else {
printf("%d\n", dp[mv[x][mv[x].size() - 2] - 1][L - 2]);
}
}else{
int y_id = mp[y];
auto it = ms[x].upper_bound(y_id);
if (it == ms[x].begin()) {
printf("0\n");
}
else {
it--;
int x_id = *it;
printf("%d\n", dp[x_id-1][L-2]);
}
}
}
}
}
}
10.行走之谜
比赛都没看题,后面再补充吧