A. Vladik and Courtesy

水题略过

#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long int LL;
int main()
{
LL a,b;
scanf("%I64d%I64d",&a,&b);
LL num=1;
while(true)
{
if(a<num){printf("Vladik\n");return 0;}
a-=num;
//b+=num;
num++;
if(b<num){printf("Valera\n");return 0;}
b-=num;
//a+=num;
num++;
}
return 0;
}

B. Vladik and Complicated Book

给定一个序列, 询问子区间【l,r】的第k小数是不是原位置的数。

显然可以用主席树维护,不过这道题数据放水了,用暴力一点的方法应该也能过。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100000 + 5; int a[N], b[N], rt[N * 20], ls[N * 20], rs[N * 20], sum[N * 20],numm[N]; int n, k, tot, sz, ql, qr, x, q, T; void Build(int& o, int l, int r){
if(l>r)return ;
o = ++ tot;
sum[o] = 0;
if(l == r) return;
int m = (l + r) >> 1;
Build(ls[o], l, m);
Build(rs[o], m + 1, r);
} void update(int& o, int l, int r, int last, int p){
o = ++ tot;
ls[o] = ls[last];
rs[o] = rs[last];
sum[o] = sum[last] + 1;
if(l == r) return;
int m = (l + r) >> 1;
if(p <= b[m]) update(ls[o], l, m, ls[last], p);
else update(rs[o], m + 1, r, rs[last], p);
} int query(int ss, int tt, int l, int r, int k){
if(l == r) return l;
int m = (l + r) >> 1;
int cnt = sum[ls[tt]] - sum[ls[ss]];
if(k <= cnt) return query(ls[ss], ls[tt], l, m, k);
else return query(rs[ss], rs[tt], m + 1, r, k - cnt);
} void work(){
scanf("%d%d%d", &ql, &qr, &x);
int xx=x;
x=(xx-ql+1);
int ans = query(rt[ql - 1], rt[qr], 1, sz, x);
if(b[ans]==numm[xx])printf("Yes\n");
else printf("No\n");
} int main(){//freopen("t.txt","r",stdin);
T=1;
while(T--){
scanf("%d%d", &n, &q);
for(int i = 1; i <= n; i ++) scanf("%d", a + i), numm[i]=b[i] = a[i];
sort(b + 1, b + n + 1);
sz = unique(b + 1, b + n + 1) - (b + 1);
tot = 0;
Build(rt[0],1, sz);
//for(int i = 0; i <= 4 * n; i ++)printf("%d,rt = %d,ls = %d, rs = %d, sum = %d\n", i, rt[i], ls[i], rs[i], sum[i]);
//for(int i = 1; i <= n; i ++)a[i] = lower_bound(b + 1, b + sz + 1, a[i]) - b;
for(int i = 1; i <= n; i ++)update(rt[i], 1, sz, rt[i - 1], a[i]);
// for(int i = 0; i <= 5 * n; i ++)printf("%d,rt = %d,ls = %d, rs = %d, sum = %d\n", i, rt[i], ls[i], rs[i], sum[i]);
while(q --)work();
}
return 0;
}

C. Vladik and Memorable Trip

O(n^2)的线性dp 不要想太多。。(我都想到DAG去了。。。)

代码比较简单,可以直接看懂。

#include <bits/stdc++.h>
using namespace std; vector <int> ps [5010], cs[5010];
int s[5010] , e[5010];
bool vis[5010];
long long dp [5010];
int main()
{
int n;
scanf("%d",&n);
vector <int> a (n);
for (int i = 0; i < n; i++) {
scanf("%d",&a[i]);
if (!vis[a[i]]) s[a[i]] = i;
vis[a[i]] = 1;
e[a[i]] = i;
}
for (int i = 0; i < n; i++) vis[a[i]] = 0;
for (int i = 0; i < n; i++) {
int mx = i, rx = 0, lj = i;
for (int j = i; j < n; j++) {
if (s[a[j]] < i) break;
lj = j;
mx = max(mx,e[a[j]]);
if (!vis[a[j]]) rx ^= a[j];
vis[a[j]] = 1; if (mx <= j) {
ps[i].push_back(j);
cs[i].push_back(rx);
}
}
for (int k = lj; k >= i; k--) vis[a[k]] = 0;
}
for (int i = n-1; i >= 0; i--) {
dp[i] = dp[i+1];
for (int j = 0; j < ps[i].size(); j++) {
dp[i] = max(dp[i],dp[ps[i][j]+1]+cs[i][j]);
}
}
printf("%I64d\n",dp[0]);
}

D. Vladik and Favorite Game

第一步判断一下按钮是否反转即可。剩下的直接暴力求路径,水题。

#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define ff first
#define ss second
#define pb push_back const int N = 100 + 11; int use[N][N];
char a[N][N],b[5];
vector<pair<int,int> > v,w;
vector<int> vv; void dfs(int l, int r)
{
use[l][r]=1;
v.pb(mp(l,r));
if (a[l][r]=='F') {w=v; return;}
if (use[l-1][r]==0&&(a[l-1][r]=='.'||a[l-1][r]=='F')) dfs(l-1,r);
if (use[l+1][r]==0&&(a[l+1][r]=='.'||a[l+1][r]=='F')) dfs(l+1,r);
if (use[l][r-1]==0&&(a[l][r-1]=='.'||a[l][r-1]=='F')) dfs(l,r-1);
if (use[l][r+1]==0&&(a[l][r+1]=='.'||a[l][r+1]=='F')) dfs(l,r+1);
v.pop_back();
}
int main()
{
int n,m;
cin>>n>>m;
int l,r;
for (int i=1; i<=n; i++)
for (int j=1; j<=m; j++)
{
cin>>a[i][j];
if (a[i][j]=='F') {l=i; r=j;}
}
b[1]='L';
b[2]='R';
b[3]='U';
b[4]='D';
dfs(1,1);
for (int i=1; i<w.size(); i++)
{
if (w[i].ff==w[i-1].ff)
{
if (w[i].ss==w[i-1].ss-1) vv.pb(1); else vv.pb(2);
} else
if (w[i].ff==w[i-1].ff-1) vv.pb(3); else vv.pb(4);
}
int u1=0,u2=0;
int x=1,y=1;
for (int i=0; i<vv.size(); i++)
{
if (vv[i]==2&&u1==0)
{
cout<<"R"<<endl;
int xx,yy;
cin>>xx>>yy;
u1=1;
if (x==xx&&y==yy) {swap(b[1],b[2]); cout<<"L"<<endl; cin>>x>>y;}
} else
if (vv[i]==4&&u2==0)
{
cout<<"D"<<endl;
int xx,yy;
cin>>xx>>yy;
u2=1;
if (x==xx&&y==yy) {swap(b[3],b[4]); cout<<"U"<<endl; cin>>x>>y;}
} else
{
cout<<b[vv[i]]<<endl;
cin>>x>>y;
}
} }

  

E. Vladik and Entertaining Flags

线段树+并查集

给定一个行数为10 列数10w的矩阵,每个方块是一个整数, 给定l和r 求范围内的联通块数量 所谓联通块即数字相等。

考虑用二分的方法合并两个联通块,在合并的时候只需要标记边界的元素属于哪个块即可,不用考虑块内的元素,因为它们不会在将来的合并中使用到。

这样我们就可以做到在常数时间内合并两个块了,这样用线段树维护就没有问题了。

其实想了一下,用倍增的方法也是可以的,dp[i][k]表示从第i列开始 连续2^k列的联通块,复杂度也是O(nlogn)

所以用一个线段树维护所有的[l,r]子块,每次查询线段树即可,合并的时候要重新标号。

重点:对于每个子块,我们只需要知道边界上的元素属于这个子块的哪个联通分量即可(使用并查集维护)

比赛的时候我也是老想块中的元素怎么维护,就觉得二分难搞了,其实完全不需要考虑。。

#include <bits/stdc++.h>

using namespace std;

const int N = 10;
const int M = 100010; int n, m, q;
int a[N][M];
int state[50], mark[50]; struct Info{
int cnt;
int left[N];
int right[N]; Info() {
cnt = 0;
memset(left, 0, sizeof left);
memset(right, 0, sizeof right);
}
} tr[M << 2]; Info join(Info &u, Info &v, int p) {
Info f;
f.cnt = u.cnt + v.cnt;
memset(state, 0, sizeof state);
for (int k = 0; k < n; k++) {
if (a[k][p] == a[k][p + 1]) {
int x = u.right[k];
int y = v.left[k] + 21;
while (state[x]) {
x = state[x];
}//路径压缩
while (state[y]) {
y = state[y];
}
if (x != y) {
f.cnt--;
state[y] = x;
}
}
}
int g = 1;
memset(mark, 0, sizeof mark);
for (int k = 0; k < n; k++) {
int x = u.left[k];
while (state[x]) {
x = state[x];
}
if (mark[x] == 0) {
mark[x] = g++;
}//从头标号 只需记录左边界和右边界
f.left[k] = mark[x];//重新标记边界
int y = v.right[k] + 21;
while (state[y]) {
y = state[y];
}
if (mark[y] == 0) {
mark[y] = g++;
}
f.right[k] = mark[y];//重新标记边界
}
return f;
} void build(int l, int r, int i) {
if (l == r) {
for (int k = 0; k < n; k++) {
if (k == 0 || a[k][l] != a[k - 1][l]) {
tr[i].left[k] = tr[i].right[k] = ++tr[i].cnt;
} else {
tr[i].left[k] = tr[i].right[k] = tr[i].left[k - 1];
}
}
} else {
int mid = (l + r) >> 1;
build(l, mid, i + i);
build(mid + 1, r, i + i + 1);
tr[i] = join(tr[i + i], tr[i + i + 1], mid);
}
/*
cout << " + " << l << " " << r << "\n";
for (int k = 0; k < n; k++) {
cout << tr[i].left[k] << " ";
}
cout << "\n";
for (int k = 0; k < n; k++) {
cout << tr[i].right[k] << " ";
}
cout << "\n";
*/
} void get(int l, int r, int x, int y, int i, Info &res) {
if (x <= l && r <= y) {
if (l == x) {
res = tr[i];
} else {
res = join(res, tr[i], l - 1);
}
} else {
int mid = (l + r) >> 1;
if (mid >= x) {
get(l, mid, x, y, i + i, res);
}
if (mid < y) {
get(mid + 1, r, x, y, i + i + 1, res);
}
}
} int main() {
scanf("%d %d %d", &n, &m, &q);
for (int i = 0; i < n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d", &a[i][j]);
}
}
build(1, m, 1);
Info res;
while (q--) {
int l, r;
scanf("%d %d", &l, &r);
get(1, m, l, r, 1, res);
printf("%d\n", res.cnt);
}
}

  

codeforces round 416 div2 补题 CF 811 A B C D E的更多相关文章

  1. codeforces round 422 div2 补题 CF 822 A-F

    A I'm bored with life 水题 #include<bits/stdc++.h> using namespace std; typedef long long int LL ...

  2. codeforces round 421 div2 补题 CF 820 A-E

    A Mister B and Book Reading  O(n)暴力即可 #include<bits/stdc++.h> using namespace std; typedef lon ...

  3. Codeforces round 419 div2 补题 CF 816 A-E

    A Karen and Morning 水题 注意进位即可 #include<bits/stdc++.h> using namespace std; typedef long long i ...

  4. codeforces round 418 div2 补题 CF 814 A-E

    A An abandoned sentiment from past 水题 #include<bits/stdc++.h> using namespace std; int a[300], ...

  5. codeforces round 417 div2 补题 CF 812 A-E

    A Sagheer and Crossroads 水题略过(然而被Hack了 以后要更加谨慎) #include<bits/stdc++.h> using namespace std; i ...

  6. codeforces round 420 div2 补题 CF 821 A-E

    A Okabe and Future Gadget Laboratory 暴力 #include<bits/stdc++.h> using namespace std; typedef l ...

  7. Educational Codeforces Round 23 A-F 补题

    A Treasure Hunt 注意负数和0的特殊处理.. 水题.. 然而又被Hack了 吗的智障 #include<bits/stdc++.h> using namespace std; ...

  8. codeforces 447 A-E div2 补题

    A DZY Loves Hash 水题 #include<iostream> #include<cstdio> #include<cstdlib> #include ...

  9. codeforces round #416 div2

    A:暴力模拟 #include<bits/stdc++.h> using namespace std; int a, b; int main() { scanf("%d%d&qu ...

随机推荐

  1. 常见的awk内建变量

    FS: 输入字段分隔符变量 语法: $ awk -F 'FS' 'commands' inputfilename 或者 $ awk 'BEGIN{FS="FS";}' OFS: 输 ...

  2. linux虚拟环境搭建

    一.virtualenv的安装与使用 1.安装virtualenv pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple virtualen ...

  3. Hdu 5274 Dylans loves tree (树链剖分模板)

    Hdu 5274 Dylans loves tree (树链剖分模板) 题目传送门 #include <queue> #include <cmath> #include < ...

  4. SpringBoot第十六篇:自定义starter

    作者:追梦1819 原文:https://www.cnblogs.com/yanfei1819/p/11058502.html 版权声明:本文为博主原创文章,转载请附上博文链接! 前言   这一段时间 ...

  5. pdf & background

    pdf & background 设置 chrome pdf background error OK

  6. 状态压缩DP总结

    POJ1185 炮兵部队问题: 在平原上才能放置炮兵,每个炮兵的上下左右2格之内都不能出现别的炮兵 可以考虑在当前行放置炮兵它的右侧和下侧绝对不会出现炮兵即可,左侧和上侧就能省去考虑 明显的状态压缩d ...

  7. codeforces Gym 100814 A、B、F、I

    A题 先求出来这个数是第几大  阶乘求概率p  然后计算获得胜率的概率 常规解法把所有情况考虑一遍(跳1次,2次,3次……)要用到组合数  数可能太大了会爆的行不通 我们观察发现它有递推性质,从第二大 ...

  8. Help Jimmy DP

    Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的平台.地面是最低的平台,高度为零,长度无限. Jimmy老鼠在时刻0从高于所有平台的某处开始下落, ...

  9. World is Exploding 树状数组+离散化

    Given a sequence A with length n,count how many quadruple (a,b,c,d) satisfies: a≠b≠c≠d,1≤a<b≤n,1≤ ...

  10. [bzoj1510][POI2006]Kra-The Disks_暴力

    Kra-The Disks bzoj-1510 POI-2006 题目大意:题目链接. 注释:略. 想法:不难发现其实只有前缀最小值是有效的. 进而我们把盘子一个一个往里放,弄一个自底向上的指针往上蹦 ...