K-Kabaleo Lite
题意及思路
第一个难点就是对原本两个数组的处理,一个是前缀和,一个使其递减
第二个难点是long long会爆精度,写不好__in128,我选择用两个数存储高位和低位。
插一句,函数返回值一定不要写错,否则会段错误。。。
代码(wrong,只能过75%数据,有空再挣扎一下。。。)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const long long MOD = 1e14;
long long a[N], p[N], b[N], num[N];
int solve(int len) {
num[0] = b[0];
p[0] = a[0];
int k = 1;
for(int i = 1; i < len; i++) {
b[i] = min(b[i],b[i-1]);
if(a[i] > 0) {
p[k] = a[i];
num[k] = b[i];
k++;
}
else {
a[i+1] += a[i];
}
}
return k;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n,t;
cin>>t;
for(int i = 1; i <= t; i++) {
memset(num,0,sizeof(num));
memset(p,0,sizeof(p));
cin>>n;
long long ans = 0,temp = 0;
for(int j = 0; j < n; j++) {
cin>>a[j];
}
for(int j = 0; j < n; j++) {
cin>>b[j];
}
int l = solve(n);
for(int j = 0; j < l; j++) {
temp += p[j]*num[j];
ans += temp/MOD;
temp %= MOD;
}
printf("Case #%d: %lld ",i,b[0]);
if(ans) printf("%lld%014lld\n",ans,abs(temp));
else printf("%lld\n",temp);
//cout<<ans<<endl;
}
return 0;
}
代码(AC)
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
const long long MOD = 1e14;
long long a[N], p[N], b[N];
void solve(int n) {
p[0] = a[0];
for(int i = 1; i < n; i++) {
b[i] = min(b[i],b[i-1]);
p[i] = a[i] + p[i-1];
}
int p1 = 0, p2 = 0;
long long ans = 0, gw = 0;
ans = p[0] * b[0];
while(p2 < n) {
while(p2 < n && p[p2] <= p[p1])
p2++;
if(p2 == n) break;
ans +=b[p2] * (p[p2] - p[p1]);
gw += ans/MOD;
ans %= MOD;
p1 = p2;
}
if(gw) printf("%lld%014lld\n",gw,ans);
else printf("%lld\n",ans);
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int n,t;
cin>>t;
for(int i = 1; i <= t; i++) {
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(p,0,sizeof(p));
cin>>n;
for(int j = 0; j < n; j++) {
cin>>a[j];
}
for(int j = 0; j < n; j++) {
cin>>b[j];
}
printf("Case #%d: %lld ",i,b[0]);
solve(n);
//cout<<ans<<endl;
}
return 0;
}
I -Interesting Computer Game
题意及思路
题目:给定N,一共N轮,每一轮给定两个数,每次只能选择一个数,要求最后经过N轮选择数的数量达到最大。
第一步:对于每一轮输入的两个数,都需要标记是否出现过,可以用一个map做离散化,key作为这个数值,value作为标记,比用二维数组节省了很多空间
第二步:用并查集,主要就是两个函数,find()查找父节点,merge()使两个点的父节点一致,同时再使用一个数组标记是否出现了环,例如【1,2】,【3,2】,【1,3】,出现了则标记2(他们的父节点),当一个点作为父节点(即fa[i] = i),即删去这个点,仅有当出现环(c[i] = 1),则不做处理,保留。
代码
注意父节点数组要开到两倍大小,否则会越界,还有判别数组c数组
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 5;
map<int,int> q;
int a[N],b[N],fa[2*N],c[2*N];
int find(int x) {
if(x == fa[x]) return x;
return fa[x] = find(fa[x]);
}
void merge(int x,int y) {
int fx = find(x);
int fy = find(y);
if(fx != fy) {
fa[fx] = fy;
if(c[fx] != 0 || c[fy] != 0) {
//cout<<'a'<<endl;
c[fy] = 1, c[fx] = 0;
}
return;
}
//cout<<"a"<<endl;
c[fy] = 1;
return;
}
int main() {
int n,t;
scanf("%d",&t);
for(int j = 1; j <= t; j++) {
scanf("%d",&n);
int k = 0;
q.clear();
for(int i = 0; i < n; i++) {
scanf("%d %d",&a[i],&b[i]);
if(!q[a[i]]) q[a[i]] = ++k;
if(!q[b[i]]) q[b[i]] = ++k;
}
fill(c+1,c+k+1,0);
for(int i = 1; i <= k; i++) fa[i] = i;
for(int i = 0; i < n; i++) {
merge(q[a[i]], q[b[i]]);
}
int ans = k;
for(int i = 1; i <= k; i++)
if(fa[i] == i && !c[i])
ans--;
printf("Case #%d: %d\n",j,ans);
}
return 0;
}
Game SET
题意及分析
暴力乱搞一搞就过了,因为n很小所以不用担心时间复杂度,因为集合没清零,卡了三次错才发现,保留的注释可以输出每个属性用来测试数据哪里出错挺好的。
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 300;
string s[N][5];
set<string> q[4];
inline string read() {
string q;
char ch = getchar();
while((ch < 'a' || ch > 'z') && ch != '*') {
ch = getchar();
}
while((ch >= 'a' && ch <= 'z') || ch == '*') {
q += ch;
ch = getchar();
}
return q;
}
bool solve(int i, int j, int k, int t) {
q[i].insert(s[j][i]);
q[i].insert(s[k][i]);
q[i].insert(s[t][i]);
/*for(auto it = q[i].begin();it != q[i].end(); it++)
cout<<*it<<" ";
cout<<endl;*/
if(q[i].size() == 2 && q[i].find("*") == q[i].end())
return false;
return true;
}
int main() {
int t,n;
scanf("%d",&t);
for(int j = 1; j <= t; j++) {
scanf("%d",&n);
for(int i = 0; i < n; i++) {
s[i][0] = read();
s[i][1] = read();
s[i][2] = read();
s[i][3] = read();
}
/*for(int i = 0; i < n; i++) {
cout<<s[i][0]<<" ";
cout<<s[i][1]<<" ";
cout<<s[i][2]<<" ";
cout<<s[i][3]<<endl;
}*/
int f = 0;
for(int i = 0; i < n-2; i++) {
for(int k = i+1; k < n-1; k++) {
for(int m = k+1; m < n; m++) {
for(int p = 0;p < 4; p ++)
q[p].clear();
bool f0 = solve(0,i,k,m);
bool f1 = solve(1,i,k,m);
bool f2 = solve(2,i,k,m);
bool f3 = solve(3,i,k,m);
if(f1&f2&f3&f0) {
f = 1;
printf("Case #%d: %d %d %d\n",j,i+1,k+1,m+1);
break;
}
else continue;
}
if(f == 1) break;
}
if(f == 1) break;
}
if(!f) printf("Case #%d: -1\n",j);
}
return 0;
}