A
判断下5个名字出现了几次.pre数据巨弱,就这么一水题在std测刷掉了非常多的人..
/** @Date : 2017-10-24 16:04:41
* @FileName: A.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
string a;
map<string, int>q;
string t[5] = { "Danil", "Olya", "Slava", "Ann" , "Nikita"};
int main()
{
q["Danil"] = 1;
q["Olya"] = 1;
q["Slava"] = 1;
q["Ann"] = 1;
q["Nikita"] = 1;
cin >> a;
int cnt = 0;
for(int i = 0; i < a.length(); i++)
{
for(int j = 0; j < 5; j++)
{
string tmp;
for(int k = 0; k < t[j].length(); k++)
tmp+=a[i + k];
//cout << tmp << endl;
if(tmp == t[j])
{
i += t[j].length() - 1, cnt++;
break;
}
}
}
printf("%s\n", cnt==1?"YES":"NO");
return 0;
}
B
DP思维,记忆化搜索,前后缀什么的都可以.dp[i]['a'/'b']代表到第i个字符时,此时以a结尾和以b结尾的最大长度,也就是a~a和a~b两种串的长度,这样从后往前再扫一遍,合并统计一下取最大值.所以当前为a则必须从a串转移,为b则从a串和ab串中大的转移就好了.这思路还是队友提供的orz 还有种巨短代码的思路其实也比较接近,维护a ab aba的数量不断取大值.
/** @Date : 2017-10-24 10:43:38
* @FileName: B.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
char a[5050];
int pre[5050][2];
int suf[5050][2];
int main()
{
scanf("%s", a + 1);
int n = strlen(a + 1);
MMF(pre);
MMF(suf);
for(int i = 1; i <= n; i++)
{
if(a[i] == 'a')
{
pre[i][0] = pre[i - 1][0] + 1;
pre[i][1] = pre[i - 1][1];
}
else if(a[i] == 'b')
{
pre[i][1] = max(pre[i - 1][0], pre[i - 1][1]) + 1;
pre[i][0] = pre[i - 1][0];
}
}
for(int i = n; i >= 1; i--)
{
if(a[i] == 'a')
{
suf[i][0] = suf[i + 1][0] + 1;
suf[i][1] = suf[i + 1][1];
}
else
{
suf[i][1] = max(suf[i + 1][0], suf[i + 1][1]) + 1;
suf[i][0] = suf[i + 1][0];
}
}
int ma = 0;
for(int i = 0; i <= n; i++)
{
int x = max(pre[i][0] + suf[i][1], pre[i][1] + suf[i][0]);
int y = max(pre[i][0] + suf[i + 1][0], pre[i][1] + suf[i + 1][1]);
ma = max(ma, max(x, y));
}
cout << ma << endl;
return 0;
}
C
贪心构造,画一下就知道,炸一个格子会把剩余1次的分到两边去,然后每隔一个格子炸一次,那么就尽可能的把剩余1次的分到了没炸的地方上,同理再进行这样2遍,就能保证炸完所有坦克了,然后注意长度为奇数时,第一遍必定要先炸偶数格,因为这样保证了炸了2遍的格子数比炸一遍的格子数要少1.
/** @Date : 2017-10-24 10:38:35
* @FileName: C 构造.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
int ans[5*N];
int main()
{
int n;
cin >> n;
int cnt = 0;
for(int i = 2; i <= n; i+=2)
ans[cnt++] = i;
for(int i = 1; i <= n; i+=2)
ans[cnt++] = i;
for(int i = 2; i <= n; i+=2)
ans[cnt++] = i;
printf("%d\n", cnt);
for(int i = 0; i < cnt; i++)
printf("%d%s", ans[i], i==cnt-1?"\n":" ");
return 0;
}
D
BFS,4方向一次可走k步询问终点最小消费次数.注意题目说每次只能一个方向最多走k步...那么简单了,但是要注意有个小细节留在了std测,一个格子的一个方向各可以被走一次...不要直接把格子全部标记了..
/** @Date : 2017-10-24 14:12:19
* @FileName: D bfs.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
int n, m, k;
int sx, sy, tx, ty;
char mp[1010][1010];
int vis[1010][1010][4];
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int bfs()
{
queue<pair<pair<int,int> ,int> >q;
q.push({{sx, sy}, 0});
MMI(vis[sx][sy]);
while(!q.empty())
{
pair<pair<int,int>, int> nw = q.front();
q.pop();
//cout << nw.fi.fi << " " << nw.fi.se << endl;
if(nw.fi.fi == tx && nw.fi.se == ty)
return nw.se;
for(int i = 0; i < 4; i++)
{
for(int j = 1; j <= k; j++)
{
int x = nw.fi.fi + dir[i][0]*j;
int y = nw.fi.se + dir[i][1]*j;
if(x < 1 || x > n || y < 1 || y > m || vis[x][y][i] || mp[x][y] == '#')
break;
vis[x][y][i] = 1;
q.push({{x, y}, nw.se + 1});
}
}
}
return -1;
}
int main()
{
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i++)
scanf("%s", mp[i] + 1);
scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
int ans = bfs();
printf("%d\n", ans);
return 0;
}
E
DFS序 线段树,对子树询问1的数量,对子树把1变0,0变1.DFS得到序,用线段树维护和就好了..
/** @Date : 2017-10-24 11:19:57
* @FileName: E DFS序 线段树.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 2e5+20;
const double eps = 1e-8;
int pos[N];
int r[N];
int cnt = 0;
struct sion{
int nxt, to;
}eg[N * 2];
int head[N * 2];
int tot;
int init()
{
MMF(pos);
MMF(pos);
MMF(r);
MMG(head);
tot = cnt = 0;
}
void add(int x, int y)
{
eg[tot].to = y;
eg[tot].nxt = head[x];
head[x] = tot++;
}
struct yuu
{
int l, r;
int add, sum;
}tt[N << 2];
inline void pushup(int rt)
{
tt[rt].sum = (tt[rt << 1].sum + tt[rt << 1 | 1].sum);
}
void pushdown(int rt)
{
if(tt[rt].add != 0)
{
tt[rt << 1].add ^= tt[rt].add;
tt[rt << 1 | 1].add ^= tt[rt].add;
tt[rt << 1].sum = tt[rt << 1].r - tt[rt << 1].l + 1 - tt[rt << 1].sum;
tt[rt << 1 | 1].sum = tt[rt << 1 | 1].r - tt[rt << 1 | 1].l + 1 - tt[rt << 1 | 1].sum;
tt[rt].add ^= 1;
}
}
void build(int l, int r, int rt)
{
tt[rt].l = l;
tt[rt].r = r;
tt[rt].add = tt[rt].sum = 0;
if(l == r)
return ;
int mid = (l + r) >> 1;
build(l, mid, rt << 1);
build(mid + 1, r, rt << 1 | 1);
}
void update(int l, int r, int rt)
{
if(l <= tt[rt].l && r >= tt[rt].r)
{
tt[rt].add ^= 1;
tt[rt].sum = tt[rt].r - tt[rt].l + 1 - tt[rt].sum;
return ;
}
pushdown(rt);
int mid = (tt[rt].l + tt[rt].r) >> 1;
if(l <= mid)
update(l, r, rt << 1);
if(r > mid)
update(l, r, rt << 1 | 1);
pushup(rt);
}
int query(int l, int r, int rt)
{
if(l <= tt[rt].l && r >= tt[rt].r)
return tt[rt].sum;
pushdown(rt);
int ans = 0;
int mid = (tt[rt].l + tt[rt].r) >> 1;
if(l <= mid)
ans += query(l, r, rt << 1);
if(r > mid)
ans += query(l, r, rt << 1 | 1);
return ans;
}
int dfs(int x, int pre)
{
pos[x] = ++cnt;
for(int i = head[x]; ~i; i = eg[i].nxt)
{
if(eg[i].to == pre)
continue;
dfs(eg[i].to, x);
}
r[x] = cnt;
}
int main()
{
int n;
cin >> n;
init();
for(int i = 2; i <= n; i++)
{
int y;
scanf("%d", &y);
add(i, y);
add(y, i);
}
build(1, n, 1);
dfs(1, -1);
for(int i = 1; i <= n; i++)
{
int v;
scanf("%d", &v);
//cout << "~" << v<<endl;
if(v) update(pos[i], pos[i], 1);
}
int q;
cin >> q;
char bf[4];
while(q--)
{
int x;
scanf("%s%d", bf, &x);
if(bf[0] == 'p')
update(pos[x], r[x], 1);
else printf("%d\n", query(pos[x], r[x], 1));
}
return 0;
}
F
莫队,离散化,询问区间内的a,b两种书数量之差为k的子区间数量,看到note里的说明和这题意就让人感觉是莫队了,可以先维护下差值的前缀和,然后map存每个前缀和的-k +0 +k这三种值,然后暴力分块转移,但是这里有个问题,普通的1e18数组hash不了,直接用map每次取数暴力转移时logn的复杂度又会超时,而注意到其数目只有1e5*3,那么可以离散化掉3e5个这些数,然后二分预处理出这三种类型的前缀和出现的第一个位置,那么在分块转移的时候,将数量统计在cnt里,利用这个下标进行差分就可以了...
/** @Date : 2017-10-24 18:07:23
* @FileName: F.cpp
* @Platform: Windows
* @Author : Lweleth (SoungEarlf@gmail.com)
* @Link : https://github.com/
* @Version : $Id$
*/
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;
int n, q;
int f[N];
int blc[N];
LL k;
LL sum[N];
LL cnt[N * 3];
vector<LL>t;
LL p[N][3];
LL res[N];
struct yuu
{
LL id, l, r;
bool operator <(const yuu &b) const
{
if(blc[l] != blc[b.l])
return l < b.l;
return r < b.r;
}
};
yuu b[N];
int main()
{
scanf("%lld%lld", &n, &k);
int sqr = sqrt(1.0 * n);
for(int i = 1; i <= n; i++)
scanf("%d", f + i), blc[i] = i / sqr;
for(int i = 1; i <= n; i++)
{
LL x;
scanf("%lld", &x);
x *= (f[i]==1?1LL:-1LL);
sum[i] = sum[i - 1] + x;
t.PB(sum[i] - k);
t.PB(sum[i]);
t.PB(sum[i] + k);
}
//别忘了0的差值
t.PB(-k);//
t.PB(0);//
t.PB(k);//
//
sort(t.begin(), t.end());
for(int i = 0; i <= n; i++)
{
p[i][0] = lower_bound(t.begin(), t.end(), sum[i] - k) - t.begin();
p[i][1] = lower_bound(t.begin(), t.end(), sum[i]) - t.begin();
p[i][2] = lower_bound(t.begin(), t.end(), sum[i] + k) - t.begin();
}
/*for(int j = 0; j <= n; j++)
printf("%2d ", sum[j]);
cout <<endl;
for(int i = 0; i < 3; i++, cout<<endl)
for(int j = 0; j <= n; j++)
printf("%2d ", p[j][i]);*/
scanf("%d", &q);
for(int i = 1; i <= q; i++)
{
scanf("%lld%lld", &b[i].l, &b[i].r);
b[i].id = i;
}
sort(b + 1, b + q + 1);
LL L = 1, R = 0;
LL ans = 0;
cnt[p[0][1]] = 1;
for(int i = 1; i <= q; i++)
{
while(L > b[i].l)//
--L, ans += cnt[p[L - 1][2]], ++cnt[p[L - 1][1]];
while(L < b[i].l)
--cnt[p[L - 1][1]], ans -= cnt[p[L - 1][2]], ++L;
while(R > b[i].r)
--cnt[p[R][1]], ans -= cnt[p[R][0]], --R;
while(R < b[i].r)
++R, ans += cnt[p[R][0]], ++cnt[p[R][1]];
res[b[i].id] = ans;
}
for(int i = 1; i <= q; i++)
printf("%lld\n", res[i]);
return 0;
}