Problem A. Lazy Spelling Bee
Problem B. Robot Rock Band
Problem C. Not So Random
Problem D. Sums of Sums
2016年的最后一场测试,参加人数看起来少了很多,可能要过年了吧,而且大多数人找到工作就没兴趣刷了……
1. 这个题很简单,对于每个字符,如果跟左边,右边都不同,左右两个字符也不同!!!!(这点很容易忽略)那就有3种情况,如果左右字符和自己都相同就是一种情况,其它都是两种情况。,每个字符都算一下后,乘起来就是答案
2. 又是一道先计算一遍中间结果存起来然后再找的题,把a^b^c^d=K变成a^b=K^d^c,然后遍历a,b村结果,再遍历d,c对每个K^d^c 查有没有对应的a^b就好了
3. 这个题又是一道一层一层滑动往下找的题,和2015B的那个酒杯题很像。因为按照题目的方法,产生重复数字的概率很高,所以不用担心存了太多数字,对当前层的每个数字都做一次三种操作,把新数字和对应概率存到下一层,具体思路一看代码就懂
4. 这道题大数据非常难,lz研究了好几个小时,具体做法相当复杂,最终的时间复杂度是O(n*logn*logn)。 具体做法分两个部分
1.比如 5,4,3,2,1 生成的数组是[1, 2, 3, 3, 4, 5, 5, 6, 7, 9, 9, 10, 12, 14, 15],如何快速求出第i个到第j个的和?
把 5,4,3,2,1 这么写
5 5 5
5 4 9 14
5 4 3 12 26
5 4 3 2 14 40
5 4 3 2 1 15 55
如果我想求红色数字的和,应该怎么做? 这里蓝色的存的是每一行的和,绿色存的是自己合往上所有行的和
求红色部分的和,直接用绿色部分 55-26 得到29 再减去 两个蓝色第一行的5 就可以得出 19
这是第一个要注意的
第二个要注意的,是双重二分查找(你没看错,二分里面套二分)
同样还是把5,4,3,2,1这样写
5 4,3,2,1
4,3,2,1
3,2,1
2,1
1
比如我们想找第3个到第8个数字的和,那么第三个数字是谁?
我们不知道,但是我们可以二分找到它
假设第三个数字是10,那么对于那个三角矩阵
第一行5 小于10,5+4小于10,所以10前面有5,5+4
第二行4小于10,4+3小于10,4+3+2小于10,4+3+2+1等于10 注意等于号,说明我们要假设的数字是存在的,把等于的单独记录
第三行全都小于10
第四行,第五行同理,所以10前面共有 2+3+3+2+1 个小于10,一个等于10,所以10存在但不是第三个数字。那么二分上限取10,再继续找
注意如果一行的数字特别多,那么预先存一个sum数组如 [5,9,12,14,15]利用二分可以迅速定位要查找数字的位置
我们确定了第3个,第八个数字都是谁,也记录了这辆数字在每一层的index,接下来就是对每一层求和,注意在方法1中提到的如何求和,别去扫描数组一个一个加那样复杂度还是O(n2),就可以了
最后,一定一定要注意的是要用long long 存结果,别都做完了结果大数据在这里翻了船……
基本思路就到这里了,但是其实要注意的小细节里面还挺多的,尤其是index从0还是从1开始之类的,无比之烦,想锻炼自己可以做做试试
附上代码
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <hash_map>
#include <hash_set>
#include <unordered_map>
#include <unordered_set>
#include <string.h>
#include <queue>
#include <list>
#include <iomanip>
using namespace std;
#define ll long long
#define uint unsigned int
class PA
{
public:
PA(){}
string words;
int MODE = 1e9 + 7;
void SingleProcess(ofstream& fout)
{
vector<int> nums(words.length(),1);
if (words.length() == 1)
{
fout << 1;
return;
}
for (int i = 0; i < words.length(); i++)
{
if (i == 0&&i<words.length()-1)
{
if (words[i] != words[i + 1]) nums[i] = 2;
}
else if (i == words.length() - 1 && i>0)
{
if (words[i] != words[i - 1]) nums[i] = 2;
}
else
{
if (words[i] != words[i + 1] && words[i] != words[i - 1]&&words[i+1]!=words[i-1]) nums[i] = 3;
else if (words[i] == words[i + 1] && words[i] == words[i - 1]) nums[i] = 1;
else nums[i] = 2;
}
}
ll ret = 1;
for (int i = 0; i < nums.size(); i++)
{
ret *= nums[i];
ret %= MODE;
}
fout << ret;
}
void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
for (int time = 0; time < Cases; time++)
{
char ch[1024];
cin >> ch;
words = ch;
fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};
class PB
{
public:
PB(){}
int N, K;
vector<int> A, B, C, D;
void SingleProcess(ofstream& fout)
{
map<int,int> abmap;
map<int, int>::iterator iter;
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
abmap[A[i] ^ B[j]]++;
}
}
ll count = 0;
for (int i = 0; i < N; i++)
{
int t = K^D[i];
for (int j = 0; j < N; j++)
{
iter = abmap.find(t^C[j]);
if (iter != abmap.end()) count += iter->second;
}
}
fout << count;
}
void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
for (int time = 0; time < Cases; time++)
{
cin >> N >> K;
A.resize(N);
B.resize(N);
C.resize(N);
D.resize(N);
for (int i = 0; i < N; i++)
{
cin >> A[i];
}
for (int i = 0; i < N; i++)
{
cin >> B[i];
}
for (int i = 0; i < N; i++)
{
cin >> C[i];
}
for (int i = 0; i < N; i++)
{
cin >> D[i];
}
fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};
class PC
{
public:
PC(){}
int N, X, K, A, B, C;
void SingleProcess(ofstream& fout)
{
map<int, double> level1, level2;
map<int, double>* currLevel, *nextLevel;
double pa = A / 100.0;
double pb = B / 100.0;
double pc = C / 100.0;
level1[X] = 1;
currLevel = &level1;
nextLevel = &level2;
for (int i = 0; i < N; i++)
{
nextLevel->clear();
for (map<int, double>::iterator iter = currLevel->begin(); iter != currLevel->end(); iter++)
{
(*nextLevel)[iter->first&K] += iter->second*pa;
(*nextLevel)[iter->first|K] += iter->second*pb;
(*nextLevel)[iter->first^K] += iter->second*pc;
}
swap(nextLevel, currLevel);
}
double ret = 0;
for (map<int, double>::iterator iter = currLevel->begin(); iter != currLevel->end(); iter++)
{
ret += iter->first*iter->second;
}
fout << setprecision(10) << fixed << ret;
}
void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
for (int time = 0; time < Cases; time++)
{
cin>>N>>X>>K>>A>>B>>C;
fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};
class PD
{
public:
PD(){}
int N,Q;
vector<ll> initArray;
vector<pair<ll, ll>> queries;
vector<ll> sumValue, sumsumValue;
void findBound(vector<pair<ll, ll>>& bound, ll index,ll& target,ll& more)
{
ll lower = 0;
ll upper = sumValue.back() + 1;
target = (lower + upper) / 2;
while (true)
{
ll total = 0;
ll equal = 0;
for (int i = 0; i < N; i++)
{
if (target < initArray[i])
{
bound[i].first = bound[i].second = 0;
continue;
}
else if (target>=sumValue[N] - sumValue[i])
{
bound[i].first = N - i;
if (target == sumValue[N] - sumValue[i]) bound[i].second = 1;
else bound[i].second = 0;
total += bound[i].first;
equal += bound[i].second;
if (total - equal > index) break;
}
else
{
ll left = i;
ll right = N;
ll mid = (left + right) / 2;
while (left != right - 1)
{
if (sumValue[mid] - sumValue[i] > target) right = mid;
else left = mid;
mid = (left + right) / 2;
}
bound[i].first = left-i;
if (sumValue[left] - sumValue[i] == target) bound[i].second = 1;
else bound[i].second = 0;
total += bound[i].first;
equal += bound[i].second;
if (total - equal > index) break;
}
}
if (equal > 0 && total - equal <= index&&total > index)
{
more = equal - (total - index);
return;
}
if (total>index)
{
upper = target;
target = (lower + upper) / 2;
}
else
{
lower = target;
target = (lower + upper) / 2;
}
}
}
void SingleProcess(ofstream& fout)
{
sumValue[0] = sumsumValue[0] = 0;
for (int i = 0; i < initArray.size(); i++)
{
sumValue[i+1] = sumValue[i] + initArray[i];
sumsumValue[i+1] = sumsumValue[i] + sumValue[i+1];
}
vector<pair<ll, ll>> leftBound(N), rightBound(N);
ll leftTarget, rightTarget, leftMore, rightMore;
for (int i = 0; i < Q; i++)
{
findBound(leftBound,queries[i].first-1,leftTarget,leftMore);
findBound(rightBound, queries[i].second-1,rightTarget,rightMore);
ll sum = 0;
for (int j = 0; j < N; j++)
{
ll l = j + leftBound[j].first - leftBound[j].second;
ll r = j + rightBound[j].first - rightBound[j].second;
sum += sumsumValue[r] - sumsumValue[l] - sumValue[j] * (r - l);
}
sum -= leftTarget*leftMore;
sum += rightTarget*(rightMore+1); //注意算上自己
fout << "\n" << sum;
}
}
void run()
{
FILE* fp = freopen("in.txt", "r", stdin);
ofstream fout("out.txt");
int Cases = 0;
scanf("%d", &Cases);
for (int time = 0; time < Cases; time++)
{
cin>>N>>Q;
initArray.resize(N);
sumValue.resize(N + 1);
sumsumValue.resize(N + 1);
for (int i = 0; i < N; i++)
{
cin >> initArray[i];
}
queries.resize(Q);
for (int i = 0; i < Q; i++)
{
cin >> queries[i].first >> queries[i].second;
}
fout << "Case #" << (time + 1) << ": ";
SingleProcess(fout);
fout << endl;
std::cout << time << endl;
}
fclose(fp);
fout.close();
}
};
int main()
{
//PA p;
//PB p;
//PC p;
PD p;
p.run();
return 0;
}