18/9/21模拟赛

期望得分:100;实际得分:0  qwq

拿到题目第一眼,我去,这不是洛谷原题(仓鼠找Sugar)吗

又多看了几眼,嗯,对,除了是有多组数据外,就是原题

然后码码码。。。。自以为写的很对 qwq

评测结束后。。。为什么我T1没有输出啊啊啊。。。

经某童鞋帮忙,发现

第一次被文件输入输出坑 qwqwq。。。

加上后就A了,白丢100 pts 蓝瘦

思路:树剖分别求LCA,然后判断LCA是否在另一条路径上

不要忘记清空数组!

#include <algorithm>
#include <cstring>
#include <cstdio>
using namespace std;
const int M = ;
int T, n, m, tot;
int to[M << ], net[M << ], head[M];
int deep[M], top[M], dad[M], size[M]; void add(int u, int v) {
to[++tot] = v; net[tot] = head[u]; head[u] = tot;
to[++tot] = u; net[tot] = head[v]; head[v] = tot;
} void dfs(int now) {
size[now] = ;
deep[now] = deep[dad[now]] + ;
for (int i = head[now]; i; i = net[i])
if (to[i] != dad[now]) {
dad[to[i]] = now;
dfs(to[i]);
size[now] += size[to[i]];
}
} void dfsl(int now) {
int t = ;
if (!top[now]) top[now] = now;
for (int i = head[now]; i; i = net[i])
if (to[i] != dad[now] && size[to[i]] > size[t])
t = to[i];
if (t) {
top[t] = top[now];
dfsl(t);
}
for (int i = head[now]; i; i = net[i])
if (to[i] != dad[now] && to[i] != t)
dfsl(to[i]);
} int lca(int x, int y) {
while (top[x] != top[y]) {
if (deep[top[x]] < deep[top[y]])
swap(x, y);
x = dad[top[x]];
}
return deep[x] > deep[y] ? y : x;
} void clear() {
tot = ;
memset(to, , sizeof to);
memset(net, , sizeof net);
memset(dad, , sizeof dad);
memset(top, , sizeof top);
memset(head, , sizeof head);
memset(deep, , sizeof deep);
memset(size, , sizeof size);
} int main() {
freopen("railway.in","r",stdin);
freopen("railway.out","w",stdout);
scanf("%d", &T);
for (int q = ; q <= T; ++q) {
if (q != ) clear();
scanf("%d%d", &n, &m);
for (int i = ; i < n; ++i) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
}
dfs();
dfsl();
for (int i = ; i <= m; ++i) {
int a, b, c, d;
scanf("%d%d%d%d", &a, &b, &c, &d);
int S = lca(a, b);
int R = lca(c, d);
if (S < R) {
swap(S, R);
swap(a, c);
swap(b, d);
}
if (lca(S, c) == S || lca(S, d) == S) printf("YES\n");
else printf("NO\n");
}
}
fclose(stdin); fclose(stdout);
return ;
}

期望得分:100? 实际得分:20  (那80pts的都TLE了。。。)

思路:线段树维护区间的最大最小值,然后枚举每一个区间求解

事实证明,我真的不会算时间复杂度 qwq

#include <algorithm>
#include <cstring>
#include <cstdio> #ifdef WIN32
#define LL "%I64d\n"
#else
#define LL "%lld\n"
#endif using namespace std;
typedef long long Ll;
const int M = ;
int n, m;
Ll ans;
int ll[M << ], rr[M << ];
int maxn[M << ], minn[M << ]; void update(int now) {
maxn[now] = max(maxn[now << ], maxn[now << | ]);
minn[now] = min(minn[now << ], minn[now << | ]);
} void build(int now, int l, int r) {
ll[now] = l; rr[now] = r;
if (l == r) {
scanf("%d", &maxn[now]);
minn[now] = maxn[now];
return ;
}
int mid = (l + r) >> ;
build(now << , l, mid);
build(now << | , mid + , r);
update(now);
} int query(int now, int l, int r) {
if (ll[now] == l && rr[now] == r)
return maxn[now];
int mid = (ll[now] + rr[now]) >> ;
if (l <= mid && mid < r) return max(query(now << , l, mid), query(now << | , mid + , r));
else if (r <= mid) return query(now << , l, r);
else return query(now << | , l, r);
} int found(int now, int l, int r) {
if (ll[now] == l && rr[now] == r)
return minn[now];
int mid = (ll[now] + rr[now]) >> ;
if (l <= mid && mid < r) return min(found(now << , l, mid), found(now << | , mid + , r));
else if (r <= mid) return found(now << , l, r);
else return found(now << | , l, r);
} void clear() {
ans = ;
memset(ll, , sizeof ll);
memset(rr, , sizeof rr);
memset(maxn, , sizeof maxn);
memset(minn, , sizeof minn);
} int main() {
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
scanf("%d", &m);
for (int q = ; q <= m; ++q) {
if (q != ) clear();
scanf("%d", &n);
build(, , n);
for (int i = ; i <= n; ++i)
for (int j = i + ; j <= n; ++j)
ans += (query(, i, j) - found(, i, j));
printf(LL, ans);
}
fclose(stdin); fclose(stdout);
return ;
}

考场20pts代码

正解:因为排列是随机的,所以从每个点向后可能的差值最多 2logn 个,所以答案最多只可能有nlogn 种,用单调队列找出来统计即可

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
const double pi=acos(-);
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
#define putk() putchar(' ')
ld eps=1e-;
ll pp=;
ll mo(ll a,ll pp){if(a>= && a<pp)return a;a%=pp;if(a<)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=;for(;b;b>>=,a=mo(a*a,pp))if(b&)ans=mo(ans*a,pp);return ans;}
ll gcd(ll a,ll b){return (!b)?a:gcd(b,a%b);}
ll read(){
ll ans=;
char last=' ',ch=getchar();
while(ch<'' || ch>'')last=ch,ch=getchar();
while(ch>='' && ch<='')ans=ans*+ch-'',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
void put(ll a){
if(a<)putchar('-'),a=-a;
int top=,q[];
while(a)q[++top]=a%,a/=;
top=max(top,);
while(top--)putchar(''+q[top+]);
}
//head
#define N 210000
int n,a[N],f1[N],f2[N],q[N];
ll s[N];
void solved(){
n=read();
rep(i,,n)a[i]=read();
a[n+]=n+;
q[]=n+;
int t=;
per(i,n,){
while(t && a[q[t]]<=a[i])--t;
f1[i]=q[t];
q[++t]=i;
}
a[n+]=;
q[]=n+;
t=;
per(i,n,){
while(t && a[q[t]]>=a[i])--t;
f2[i]=q[t];
q[++t]=i;
}
rep(i,,n)s[i]=;
rep(i,,n){
int z1=i,z2=i;
while(z1!=n+ && z2!=n+){
if(f1[z1]<=f2[z2]){
int tt=max(z1,z2),zz=a[z1]-a[z2];
z1=f1[z1];
s[zz]+=max(z1,z2)-tt;
}
else{
int tt=max(z1,z2),zz=a[z1]-a[z2];
z2=f2[z2];
s[zz]+=max(z1,z2)-tt;
}
}
}
ll ans=;
rep(i,,n-)
ans+=s[i]*i;
cout<<ans<<endl;
}
int main(){
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
int T=read();
while(T--){
solved();
}
return ;
}

正解

比题解更好的做法  ——By lgj

分别求所有区间的最大值和、最小值和

用单调栈维护,用sum记录已经求过的区间的最大值的和

求最小值时,可将所有的数转为负数,重新跑一遍即可

最后将两次求出的值相加即可

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#define LL long long
using namespace std;
const LL MAXN = 1e5 + ;
inline LL read() {
char c = getchar(); LL x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
LL T, N;
LL a[MAXN], q[MAXN];
LL solve() {
LL h = , t = , ans = , sum = ;
for(LL i = ; i <= N; i++) {
while(h <= t && a[i] > a[q[t]]) sum -= a[q[t]] * (q[t] - q[t - ]), t--;
q[++t] = i;
ans += a[i] * (q[t] - q[t - ]) + sum;
sum += a[i] * (q[t] - q[t - ]);
}
return ans;
}
int main() {
freopen("count.in", "r", stdin);
freopen("count.out", "w", stdout);
T = read();
while(T--) {
N = read();
for(LL i = ; i <= N; i++) a[i] = read();
LL ans = solve();
for(LL i = ; i <= N; i++) a[i] = -a[i];
LL ans2 = solve();
cout << ans + ans2 << endl;
}
return ;
}

% lgj dalao

期望得分:0;实际得分:0

一开始以为样例错了,死活推不出来

前一个小时做了前两题,剩下的时间大部分就在推样例发呆中度过了

最后半小时才发现读错题 qwq

然而暴力也写不完了。。。

正解:对于每一条边统计有多少个区间跨过这条边即可

统计这一问题的对偶问题,有多少个区间没跨过会更方便

使用启发式合并+并查集统计子树内的,使用启发式合并+set 统计子树外的

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
const double pi=acos(-);
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define Rep(i,u) for(int i=head[u];i;i=Next[i])
#define clr(a) memset(a,0,sizeof a)
#define pb push_back
#define mp make_pair
ld eps=1e-;
ll pp=;
ll mo(ll a,ll pp){if(a>= && a<pp)return a;a%=pp;if(a<)a+=pp;return a;}
ll powmod(ll a,ll b,ll pp){ll ans=;for(;b;b>>=,a=mo(a*a,pp))if(b&)ans=mo(ans*a,pp);return ans;}
ll read(){
ll ans=;
char last=' ',ch=getchar();
while(ch<'' || ch>'')last=ch,ch=getchar();
while(ch>='' && ch<='')ans=ans*+ch-'',ch=getchar();
if(last=='-')ans=-ans;
return ans;
}
//head
#define N 110000
int head[N],Next[N*],v[N*],num,fa[N],son[N],sum[N],n,s[N],Fa[N];
ll ans=,Sum,Sum2;
bool vis[N];
set<int>Q;
set<int>::iterator it,it1,it2;
int find(int x){
if(x==Fa[x])return x;
return Fa[x]=find(Fa[x]);
}
void add(int x,int y){
v[++num]=y;Next[num]=head[x];head[x]=num;
}
void dfs1(int u){
sum[u]=;son[u]=;
for(int i=head[u];i;i=Next[i])
if(v[i]!=fa[u]){
fa[v[i]]=u;
dfs1(v[i]);
sum[u]+=sum[v[i]];
if(!son[u] || sum[v[i]]>sum[son[u]])son[u]=v[i];
}
}
ll cal(ll n){
return n*(n-)/;
}
void Add(int u){
Q.insert(u);
it=Q.find(u);
it1=it2=it;
it1--;it2++;
Sum2-=cal((*it2)-(*it1)-);
Sum2+=cal((*it)-(*it1)-)+cal((*it2)-(*it)-);
vis[u]=;
if(vis[u-]){
int fx=find(u-),fy=find(u);
Sum+=(ll)s[fx]*s[fy];
Fa[fx]=fy;
s[fy]+=s[fx];
}
if(vis[u+]){
int fx=find(u+),fy=find(u);
Sum+=(ll)s[fx]*s[fy];
Fa[fx]=fy;
s[fy]+=s[fx];
}
}
void bfs(int u){
Add(u);
for(int i=head[u];i;i=Next[i])
if(v[i]!=fa[u])bfs(v[i]);
}
void clear(int u){
s[u]=;vis[u]=;Fa[u]=u;
for(int i=head[u];i;i=Next[i])
if(v[i]!=fa[u])clear(v[i]);
}
void dfs2(int u){
for(int i=head[u];i;i=Next[i])
if(v[i]!=fa[u] && v[i]!=son[u]){
dfs2(v[i]);
clear(v[i]);
Sum=;
Q.clear();
Q.insert();
Q.insert(n+);
Sum2=(ll)(n-)*n/;
} if(son[u])dfs2(son[u]);
for(int i=head[u];i;i=Next[i])
if(v[i]!=fa[u] && v[i]!=son[u])bfs(v[i]); Add(u); ans+=(ll)n*(n-)/-Sum-Sum2;
}
int main(){
freopen("treecnt.in","r",stdin);
freopen("treecnt.out","w",stdout);
n=read();
Q.clear();
Q.insert();
Q.insert(n+);
Sum2=cal(n);
rep(i,,n)Fa[i]=i,s[i]=,vis[i]=;
rep(i,,n){
int x=read(),y=read();
add(x,y);
add(y,x);
}
dfs1();
dfs2();
cout<<ans<<endl;
return ;
}

正解

18/9/21模拟赛-Updated的更多相关文章

  1. 【2018.10.18】noip模拟赛Day2 地球危机(2018年第九届蓝桥杯C/C++A组省赛 三体攻击)

    题目描述 三体人将对地球发起攻击.为了抵御攻击,地球人派出了 $A × B × C$ 艘战舰,在太 空中排成一个 $A$ 层 $B$ 行 $C$ 列的立方体.其中,第 $i$ 层第 $j$ 行第 $k ...

  2. 18.09.22模拟赛T2 历史

    网上基本上找不到这道题,何况LJJ还稍微改了一下...... 原题:传送门 题目描述 ljj 被S 国数不清的漂亮小姐姐所吸引,为了搞清楚为什么S 国有如此多的漂亮小姐姐,他决定研究S 国的历史. 根 ...

  3. 6.18 省选模拟赛 树 倍增 LCT

    LINK:树 考虑暴力 保存每个版本的父亲 然后暴力向上跳.得分20. 考虑离线 可以离线那么就可以先把树给搞出来 然后考虑求k级祖先 可以倍增求. 如何判断合法 其实要求路径上的边的时间戳<= ...

  4. 6.18 省选模拟赛 字符串 LCT SAM

    LINK:字符串 看起来很难做 考虑一种暴力 建立SAM后每次查询暴力扫儿子. 期望得分10分.实际得分10分. 另外一种发现每次扫儿子过于暴力 可以每次儿子向上做贡献 每次都暴力向上跳. 期望得分1 ...

  5. 4.18 省选模拟赛 无聊的计算器 CRT EXBSGS EXLucas

    算是一道很毒瘤的题目 考试的时候码+调了3h才搞定. op==1 显然是快速幂. op==2 有些点可以使用BSGS 不过后面的点是EXBSGS. 这个以前学过了 考试的时候还是懵逼.(当时还是看着花 ...

  6. [10.18模拟赛] 序列 (DP)

    [10.18模拟赛] 序列 题目描述 山山有一个整数序列s1,s2,-,sn,其中1≤si≤k. 求出有多少个准确移除m个元素后不同的序列.答案模(1e9+7) 输入 输入包括几个测试用例,并且由文件 ...

  7. [GRYZ]寒假模拟赛

    写在前面 这是首次广饶一中的OIERS自编自导,自出自做(zuo)的模拟赛. 鉴于水平气压比较低,机(wei)智(suo)的WMY/XYD/HYXZC就上网FQ下海找了不少水(fei)题,经过他们优( ...

  8. CH Round #48 - Streaming #3 (NOIP模拟赛Day1)

    A.数三角形 题目:http://www.contesthunter.org/contest/CH%20Round%20%2348%20-%20Streaming%20%233%20(NOIP模拟赛D ...

  9. 7.29NOIP模拟赛

    7.29NOIP模拟赛 T1 YSG (1s,64MB,ysg.in,ysg.out) 描述 ysg,yxy,azw 三人正在刷题. 他们每做一题的时间都是一个有理数. 如果在某一时刻,三人同时做完一 ...

随机推荐

  1. PHP7内核剖析之执行流程

    以fpm为例: 1.fpm启动时,会先执行 module_startup, 并随着fpm进程常驻 2.当一个请求到达之后,会执行 request_startup, 进行一些请求初始化工作,然后执行代码 ...

  2. BZOJ 3110 [Zjoi2013]K大数查询(整体二分)

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 11654  Solved: 3505[Submit][St ...

  3. POJ 3539 Elevator(同余类BFS)

    题意 有一部电梯,最初停在1层. 电梯有4个按键,上升a,b,c层,回到一层. 求从一层出发.能到达1~h的哪些楼层. (h<=1018,a,b,c<=105) 题解 这种h能大的图论,一 ...

  4. 使用 init-runonce脚本创建一个 openstack云项目

    source /etc/kolla/admin-openrc.sh cd /usr/share/kolla-ansible ./init-runonce 报错内容 Traceback (most re ...

  5. python语法学习笔记

    函数的参数   定义函数的时候,我们把参数的名字和位置确定下来,函数的接口定义就完成了.对于函数的调用者来说,只需要知道如何传递正确的参数,以及函数将返回什么样的值就够了,函数内部的复杂逻辑被封装起来 ...

  6. [NOI2016]优秀的拆分(SA数组)

    [NOI2016]优秀的拆分 题目描述 如果一个字符串可以被拆分为 \(AABB\) 的形式,其中 A和 B是任意非空字符串,则我们称该字符串的这种拆分是优秀的. 例如,对于字符串 \(aabaaba ...

  7. CF546E Soldier and Traveling(网络流,最大流)

    CF546E Soldier and Traveling 题目描述 In the country there are \(n\) cities and \(m\) bidirectional road ...

  8. 【Codeforces Round #421 (Div. 2) A】Mister B and Book Reading

    [题目链接]:http://codeforces.com/contest/820/problem/A [题意] 每天看书能看v页; 且这个v每天能增加a; 但是v有上限v1; 然后每天还必须往回看t页 ...

  9. javaweb——登陆权限过滤器的编写

    http://blog.csdn.net/lzc4869/article/details/50935858

  10. C++调用Lua的性能測试

    游戏服务器经典的架构就是C++和Lua的结合,C++开发主体框架.Lua实现一些复杂的逻辑.我们都知道Lua是一种很快的语言.可是究竟有多块.我们測试下看看. C++调用Lua的性能測试.发现不正确的 ...