A题,因为数据范围很小,所以只要暴力即可,如果能相遇一定范围不大,如果范围很大还没相遇一定是不会相遇的了。正解应当是用扩展欧几里得计算这个方程的整数解,再想办法看看有没有正整数解才是。

  B题,只要看懂了题意,用map维护一下即可。真不知道题目给的n是干嘛用的。。

  C题,如果不存在loop的情况就用np态判断一下即可。现在存在loop正向dfs是不可以的,因为dfs的顺序会对结果造成影响。那么采用倒着搜索的方式,如果某点是必败的,那么到达这个点的点必然是必胜的,如果当前点是必胜的,那么父亲节点的计数减1(每个点的计数初始化为这个点可以走的方法数),如果该父亲节点的计数点为0了,说明其子节点都是必胜点,该点为必败点。不论是必胜点还是必败点,在得出这个点的性质后需要入队继续搜索,那么自始至终没有入队的点就是loop点了。实现完以后可以发现这个方式和拓扑排序有点类似。代码如下:

 #include <bits/stdc++.h>
#define t_mid (l+r>>1)
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls,l,t_mid
#define rson rs,t_mid+1,r
using namespace std;
const int N = + ;
typedef long long ll;
typedef pair<int,int> pii;
//typedef pair<ll, int> pli; int n;
vector<int> s[];
bool vis[N][];
int deg[N][];
int dp[N][];
struct node
{
int pos, turn, ans; // 1 : win, 0 : lose
};
void bfs()
{
queue<node> Q;
Q.push((node){, , });
Q.push((node){, , });
dp[][] = dp[][] = ;
vis[][] = vis[][] = ;
for(int i=;i<=n;i++) deg[i][] = s[].size();
for(int i=;i<=n;i++) deg[i][] = s[].size();
while(!Q.empty())
{
node temp = Q.front(); Q.pop();
int turn = temp.turn, pos = temp.pos, ans = temp.ans;
int befturn = !turn;
dp[pos][turn] = ans;
if(ans == )
{
for(int step : s[befturn])
{
int befpos = pos - step;
if(befpos <= ) befpos += n;
if(!vis[befpos][befturn])
{
vis[befpos][befturn] = ;
Q.push((node){befpos, befturn, });
}
}
}
else
{
for(int step : s[befturn])
{
int befpos = pos - step;
if(befpos <= ) befpos += n;
if(--deg[befpos][befturn] == && !vis[befpos][befturn])
{
vis[befpos][befturn] = ;
Q.push((node){befpos, befturn, });
}
}
}
}
} int main()
{
cin >> n;
int t; scanf("%d",&t);
while(t--)
{
int x; scanf("%d", &x);
s[].push_back(x);
}
sort(s[].begin(), s[].end());
scanf("%d",&t);
while(t--)
{
int x; scanf("%d", &x);
s[].push_back(x);
}
bfs();
for(int j=;j<;j++)
{
for(int i=;i<=n;i++)
{
if(!vis[i][j]) printf("Loop ");
else if(dp[i][j]) printf("Win ");
else printf("Lose ");
}
puts("");
}
return ;
}

C

  D题,1操作是u到v建边,2操作是u到[L, R]建边,3操作是[L, R]到u建边,1操作直接建边即可,2操作和3操作需要在线段树上建边,2操作需要在第一棵线段树上从父亲往子节点建权值为0的边,3操作在第二棵线段树上反过来即可。最后跑dij即可。需要注意的是,一棵线段树的空间是2N,因此总共的点数是N+2N*2=5N。要注意线段实际上是化为log个点再建边的。具体见代码:

 #include <bits/stdc++.h>
#define t_mid (l+r>>1)
#define ls (o<<1)
#define rs (o<<1|1)
#define lson ls,l,t_mid
#define rson rs,t_mid+1,r
using namespace std;
const int N = 1e5 + ;
const int V = N * ;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,int> pli;
const ll inf = 0x3f3f3f3f3f3f3f3f; int n, m, s;
vector<pii> G[V];
void addEdge(int u,int v,int w)
{
G[u].push_back(pii(v, w));
}
int id[][N<<], idx;
void build(int o,int l,int r,int who)
{
id[who][o] = ++idx;
if(l == r)
{
if(who == ) addEdge(id[who][o], l, );
else addEdge(l, id[who][o], );
return ;
}
build(lson, who);
build(rson, who);
if(who == )
{
addEdge(id[who][o], id[who][ls], );
addEdge(id[who][o], id[who][rs], );
}
else
{
addEdge(id[who][ls], id[who][o], );
addEdge(id[who][rs], id[who][o], );
}
}
vector<int> vs;
void get(int o,int l,int r,int ql,int qr,int who)
{
if(l == ql && r == qr)
{
vs.push_back(id[who][o]);
return ;
}
if(qr <= t_mid) get(lson,ql,qr,who);
else if(ql > t_mid) get(rson,ql,qr,who);
else
{
get(lson,ql,t_mid,who);
get(rson,t_mid+,qr,who);
}
} ll d[V];
void dij(int s)
{
memset(d,0x3f,sizeof d);
d[s] = ;
priority_queue<pli,vector<pli>,greater<pli> > Q;
Q.push(pli(0LL, s));
while(!Q.empty())
{
pli p = Q.top(); Q.pop();
int u = p.second;
ll dis = p.first;
if(dis > d[u]) continue;
for(pii e : G[u])
{
int v = e.first, w = e.second;
if(d[u] + w < d[v])
{
d[v] = d[u] + w;
Q.push(pli(d[v], v));
}
}
}
} int main()
{
cin >> n >> m >> s;
idx = n;
build(,,n,);
build(,,n,);
while(m--)
{
int op; scanf("%d",&op);
if(op == )
{
int u, v, w; scanf("%d%d%d",&u,&v,&w);
addEdge(u, v, w);
}
else
{
vs.clear();
int u, l, r, w;
scanf("%d%d%d%d",&u,&l,&r,&w);
if(op == )
{
get(,,n,l,r,);
for(int v : vs) addEdge(u, v, w);
}
else
{
get(,,n,l,r,);
for(int v : vs) addEdge(v, u, w);
}
}
}
dij(s);
for(int i=;i<=n;i++)
{
if(d[i] == inf) d[i] = -;
printf("%I64d%c",d[i],i==n?'\n':' ');
}
return ;
}

D

  E题,利用主席树可以在log的时间内找出一段不同的数的个数,那么对于一个k,不断的二分+主席树来找到最右边的数字个数不超过k的范围,这个复杂度是两个log,再考虑到k是从1到n,对一个k每次至少跳k个单位的距离,那么总共需要进行这个两个log的操作的次数是n/1+n/2+...+n/n = ln(n)。那么总的时间复杂度是nlogloglog,TLE。那么正确的做法是二分+主席树可以利用类似与在线段树上的树上二分操作优化成一个log,每次去寻找右边第一个个数超过k的位置并跳过去,那么最终的复杂度是nloglog,可A。要注意的是这里主席数的节点要从右往左插入。具体见代码:

 #include <bits/stdc++.h>
#define t_mid (l+r>>1)
//#define ls (o<<1)
//#define rs (o<<1|1)
//#define lson ls,l,t_mid
//#define rson rs,t_mid+1,r
using namespace std;
const int N = 1e5 + ;
typedef long long ll;
typedef pair<int,int> pii; int pre[N],a[N],n,m,tot;
int rt[N*],sum[N*],ls[N*],rs[N*];
void build(int &o,int l,int r)
{
o = ++tot;
sum[o] = ;
if(l == r) return ;
build(ls[o],l,t_mid);
build(rs[o],t_mid+,r);
}
void update(int &o,int l,int r,int last,int pos,int dt)
{
o = ++tot;
sum[o] = sum[last];
ls[o] = ls[last];
rs[o] = rs[last];
if(l == r) {sum[o] += dt; return ;}
if(pos <= t_mid) update(ls[o],l,t_mid,ls[last],pos,dt);
else update(rs[o],t_mid+,r,rs[last],pos,dt);
sum[o] = sum[ls[o]] + sum[rs[o]];
}
int query(int o,int l,int r,int k) // return the first bu man zu de r
{
if(l == r) return l;
int cnt = sum[ls[o]];
if(cnt > k) return query(ls[o],l,t_mid,k);
else return query(rs[o],t_mid+,r,k-cnt);
}
int ans[N]; int main()
{
cin >> n;
memset(pre,-,sizeof pre);
for(int i=;i<=n;i++) scanf("%d",a+i);
build(rt[],,n+); // a[n+1] = 0, but all the ai is >= 1, so is different one
for(int i=n;i>=;i--)
{
int now = a[i];
if(pre[now] == -)
{
update(rt[i],,n+,rt[i+],i,);
}
else
{
int temp;
update(temp,,n+,rt[i+],pre[now],-);
update(rt[i],,n+,temp,i,);
}
pre[now] = i;
}
for(int k=;k<=n;k++)
{
int L = , res = ;
while(L <= n)
{
int pos = query(rt[L],,n+,k);
L = pos;
res++;
}
ans[k] = res;
}
for(int i=;i<=n;i++) printf("%d%c",ans[i],i==n?'\n':' ');
return ;
}

E

CodeForces 787 题解的更多相关文章

  1. codeforces#536题解

    CodeForces#536 A. Lunar New Year and Cross Counting Description: Lunar New Year is approaching, and ...

  2. codeforces 1093 题解

    12.18 update:补充了 $ F $ 题的题解 A 题: 题目保证一定有解,就可以考虑用 $ 2 $ 和 $ 3 $ 来凑出这个数 $ n $ 如果 $ n $ 是偶数,我们用 $ n / 2 ...

  3. Codeforces Numbers 题解

    这题只需要会10转P进制就行了. PS:答案需要约分,可以直接用c++自带函数__gcd(x,y). 洛谷网址 Codeforces网址 Code(C++): #include<bits/std ...

  4. Codeforces 691E题解 DP+矩阵快速幂

    题面 传送门:http://codeforces.com/problemset/problem/691/E E. Xor-sequences time limit per test3 seconds ...

  5. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  6. Codeforces 840C 题解(DP+组合数学)

    题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...

  7. Codeforces 515C 题解(贪心+数论)(思维题)

    题面 传送门:http://codeforces.com/problemset/problem/515/C Drazil is playing a math game with Varda. Let’ ...

  8. Codeforces 475D 题解(二分查找+ST表)

    题面: 传送门:http://codeforces.com/problemset/problem/475/D Given a sequence of integers a1, -, an and q ...

  9. CodeForces CF875C题解

    题解 非常有意思的\(2-SAT\)的题. 听学长讲完之后感觉确实容易想到\(2-SAT\),顺理成章. 显然,对于两个串,对咱们来说有意义的显然是两个串中第一个不同的数字.那么,我们假设两个串分别是 ...

随机推荐

  1. POJ1611(The Suspects)--简单并查集

    题目在这里 关于SARS病毒传染的问题.在同一个组的学生是接触很近的,后面也会有新的同学的加入.其中有一位同学感染SARS,那么该组的所有同学得了SARS.要计算出有多少位学生感染SARS了.编号为0 ...

  2. 《你不知道的Javascript》感悟篇—对象属性遍历的那些事

    划重点 本篇笔者将重点介绍JavaScript中 getOwnPropertyNames .Object.keys.for ... in 的使用及他们之间的异同点. getOwnPropertyNam ...

  3. 如何使用点击超链接的方式打开Android手机上的应用

    在Android应用的AndroidManifest.xml里加入如下的配置片段: <action android:name="my_action"/> <cat ...

  4. 注册码云和使用git

    1.4.1 码云 注册码云 码云 填写信息注册后进入 创建仓库 问题:提交到码云的中文变成乱码 可以改变本机文件保存的编码为UTF-8即可 1.4.2 git git官网下载安装包 双击安装包开始安装 ...

  5. kali linux Desktop Environemt types and kali linux install virualbox

    1.we know the kali linux desktop environmet can also be costomized ,Desktop environmet can use GNOME ...

  6. RT-Thread--中断管理

    Cortex-M CPU架构基础 寄存器简介 Cortex-M 系列 CPU 的寄存器组里有 R0\~R15 共 16 个通用寄存器组和若干特殊功能寄存器,如下图所示. 通用寄存器组里的 R13 作为 ...

  7. two pointers 思想

    针对有序的序列特性做出的优化思想

  8. Laravel 队列的简单使用例子

    场景: 在一个a系统中注册一个用户时,发送请求到b系统中也注册一个相同信息的账号,考虑到网络有可能错误的原因,所以使用队列去处理 1.修改根目录 .env 文件的QUEUE_CONNECTION字段配 ...

  9. TCP三次握手,四次回收的每一步的解释

    三次握手 第一次握手:主机A发送位码为syn=1,随机产生seq number=10001的数据包到服务器,主机B由SYN=1知道,A要求建立联机,此时状态为SYN_SENT: 第二次握手:主机B收到 ...

  10. 修改git提交的用户名和密码

    目的:每个项目自定义Git提交的用户名和邮箱 1.在本地找到某个项目所在的地址 2.找到config文件 3.增加如下配置 4. ok,这样每个项目都可以定义提交者姓名和邮箱了