C News Distribution

并查集水题

D Bicolored RBS

括号匹配问题,如果给出的括号序列nesting depth为n,那么最终可以分成两个nesting depth为n / 2的序列。

在进行匹配的时候,如果当前栈中的左括号大于等于 n / 2,那么剩下的括号就要进行标记,最终标记和不标记的分成两个部分。

E Range Deleting

对一个序列去掉一个区间范围内的数字,使得剩下的序列是一个非降序的序列。

这题是一道较好的思维题。

首先可以预处理出1到\(pref\),只保留\([1,pref]\)内的数字,序列是非降序的;也可以预处理出\(suf\)到\(x\),保留\([suf,x]\)内的数字,序列是非降序的。

然后可以发现,如果去掉\([l,r]\)满足条件,那么去掉\([l,r+1],[l,r+2],...,[l,x]\)也一定是满足条件的。

可以枚举\(l\),枚举的范围是\([1,pref+1]\),\(pref+1\)是因为\([1,pref]\)的序列都是有序的,所以去掉\(pref+1\)也是有序的;对于每一个\(l\),要找出满足条件的\(r\)的数量;

因为去掉了\(l\)到某个数字,前面剩下的数字就是\([1,l-1]\),那么\(r\)满足的条件就是首先要大于等于\(suf\),大于等于\(l\),然后还要满足在\([1,l-1]\)当中出现的最大的数字的最后一个下标之前,这个数字没有出现过,换个角度,假设\([1,l-1]\)当中出现的最大的数字的最后一个下标是\(ind\),那么\(r\)的最小值就是\(max(a[1],....,a[ind])+1\),于是\(r\)的最小值就由之前的3个条件共同求出,满足条件的\(r\)的个数就分为两种情况:

1.\(l == r\),那么就有\(x - r + 1\)种;

2.\(l != r\),那么就有\(x - r + 2\)种,因为\(r\)是可以保留在序列当中的,所以可以去掉的范围是\([r-1,x]\),也就是说去掉\([l,r-1]\)这个区间也是满足条件的。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#include <set>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1e6 + 10; vector<int> G[N];
set<int> s; int pre[N],sub[N]; int a[N]; bool L[N],R[N]; int main()
{
int n,x;
scanf("%d%d",&n,&x);
for (int i = 1;i <= n;i++)
{
scanf("%d",&a[i]);
s.insert(a[i]);
}
if (x == 1)
{
puts("1");
return 0;
}
pre[0] = -inf;
for (int i = 1;i <= n;i++)
{
pre[i] = max(pre[i-1],a[i]);
}
sub[n+1] = inf;
for (int i = n;i >= 1;i--)
{
sub[i] = min(sub[i+1],a[i]);
}
for (int i = 1;i <= n;i++)
{
G[a[i]].push_back(i);
}
int pref,suf;
L[1] = 1;
for (int i = 2;i <= x;i++)
{
if (G[i].empty())
{
L[i] = L[i-1];
}
else
{
int p = G[i][0];
int x = sub[p];
if (x < i)
{
L[i] = 0;
}
else
{
L[i] = L[i-1];
}
}
}
R[x] = 1;
for (int i = x - 1;i >= 1;i--)
{
if (G[i].empty())
{
R[i] = R[i+1];
}
else
{
int sz = G[i].size();
int p = G[i][sz-1];
int x = pre[p];
if (x > i)
{
R[i] = 0;
}
else
{
R[i] = R[i+1];
}
}
}
for (int i = 1;i <= x;i++)
{
if (L[i]) pref = i;
}
for (int i = x;i >= 1;i--)
{
if (R[i]) suf = i;
} ll ans = 0; for (int i = 1;i <= x;i++)
{
if (i == 1)
{
for (int j = 1;j <= x;j++)
{
if (R[j+1])
{
ans += x - j + 1;
//printf("%d *\n",x - j + 1);
break;
}
}
}
else
{
if (!L[i-1]) break;
int l = i-1;
if (l < (*s.begin()) || l > (*--s.end()))
{
int tmp = max(l + 1,suf);
if (tmp == l + 1)
{
ans += x - tmp + 1; }
else
{
ans += x - tmp + 2;
//printf("%d *\n",x - tmp + 2);
}
}
else
{
if (G[l].empty())
{
int xx = *--s.lower_bound(l);
int sz = G[xx].size();
int p = G[xx][sz-1];
int tmp = max(pre[p] + 1,suf);
tmp = max(l + 1,tmp);
if (tmp == l + 1)
{
ans += x - tmp + 1;
}
else
{
ans += x - tmp + 2;
}
}
else
{
int sz = G[l].size();
int p = G[l][sz-1];
int tmp = max(pre[p] + 1,suf);
if (tmp == l + 1)
{
ans += x - tmp + 1;
}
else
{
ans += x - tmp + 2;
}
}
}
}
}
printf("%lld\n",ans);
return 0;
}

F Scalar Queries

题意:

有一个数组\(a\),里面的数字两两不同,\(f(l,r)\)表示选出下标从\(l\)到\(r\)的数字,然后排序,排序之后的数组为\(b\),\(\sum_{i = 1}^{r - l + 1}b_i * i\)。

需要求每一个\(f(l,r)\)的和。

思路:

又是一道很好的思维题。

可以转化为求每一个数字对最终答案的贡献。

假设\(low(l,r,a[i])\)表示在区间\([l,r]\)内小于\(a[i]\)的数字,那么\(a[i]\)对于\((l,r)\)的贡献就是\(a[i] * low(l,r,a[i])+1\)。

\(low(l,r,a[i])+1\)就相当于\(a[i]\)在\((l,r)\)内的rank。

这个rank又转化为每一个小于\(a[i]\)的数字出现的次数之和。

首先对于\(a_i\)本身,它自己出现的次数是\(i * (n - i - 1)\);

然后对于\(a_j < a_i,j < i\)的数字,它的出现次数是\(j * (n - i + 1)\);

对于\(a_j < a_i,j > i\)的数字,它的出现次数是\(i * (n - j + 1)\);

如上三个数字相加,假设为\(sum\),那么\(sum * a_i\)就是\(a_i\)对答案的贡献。

对于小于某个数字的所有数字出现的位置,可以用树状数组求前缀和。大的也同理。

又出现了\(int * int\) 爆\(int\) 的问题!!!

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 5e5 + 10;
const ll mod = 1000000000LL + 7; ll c[N],d[N]; int n; int lowbit(int x)
{
return x&(-x);
} void addl(int x,int y)
{
for (int i = x;i <= n;i += lowbit(i)) c[i] += y;
} void addr(int x,int y)
{
for (int i = x;i <= n;i += lowbit(i)) d[i] += y;
} ll getlsum(int x)
{
ll ans = 0;
for (int i = x;i >= 1;i -= lowbit(i))
{
ans += c[i];
ans %= mod;
}
return ans;
} ll getrsum(int x)
{
ll ans = 0;
for (int i = x;i >= 1;i -= lowbit(i))
{
ans += d[i];
ans %= mod;
}
return ans;
} pii a[N]; int main()
{
scanf("%d",&n);
for (int i = 1;i <= n;i++)
{
scanf("%d",&a[i].first);
a[i].second = i;
}
sort(a+1,a+1+n);
ll ans = 0;
for (int i = 1;i <= n;i++)
{
ll x = getlsum(a[i].second);
ll tmp = 0;
tmp += x * (n-a[i].second+1);
tmp %= mod;
ll y = getrsum(n-a[i].second+1);
tmp += y * a[i].second;
tmp %= mod;
tmp += 1LL * a[i].second * (n-a[i].second + 1);
tmp %= mod;
ans += tmp * a[i].first;
ans %= mod;
addl(a[i].second,a[i].second);
addr(n-a[i].second + 1,n-a[i].second+1);
}
ans += mod;
printf("%lld\n",ans % mod);
return 0;
}

codeforces Educational Codeforces Round 65 (补完)的更多相关文章

  1. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) F. Isomorphic Strings 题目连接: http://cod ...

  2. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  3. codeforces Educational Codeforces Round 5 A. Comparing Two Long Integers

    题目链接:http://codeforces.com/problemset/problem/616/A 题目意思:顾名思义,就是比较两个长度不超过 1e6 的字符串的大小 模拟即可.提供两个版本,数组 ...

  4. Codeforces Educational Codeforces Round 3 A. USB Flash Drives 水题

    A. USB Flash Drives 题目连接: http://www.codeforces.com/contest/609/problem/A Description Sean is trying ...

  5. codeforces Educational Codeforces Round 16-E(DP)

    题目链接:http://codeforces.com/contest/710/problem/E 题意:开始文本为空,可以选择话费时间x输入或删除一个字符,也可以选择复制并粘贴一串字符(即长度变为两倍 ...

  6. Codeforces Educational Codeforces Round 15 E - Analysis of Pathes in Functional Graph

    E. Analysis of Pathes in Functional Graph time limit per test 2 seconds memory limit per test 512 me ...

  7. Codeforces Educational Codeforces Round 15 D. Road to Post Office

    D. Road to Post Office time limit per test 1 second memory limit per test 256 megabytes input standa ...

  8. Codeforces Educational Codeforces Round 15 C. Cellular Network

    C. Cellular Network time limit per test 3 seconds memory limit per test 256 megabytes input standard ...

  9. Codeforces Educational Codeforces Round 5 E. Sum of Remainders 数学

    E. Sum of Remainders 题目连接: http://www.codeforces.com/contest/616/problem/E Description The only line ...

随机推荐

  1. 配置cinder-backup服务使用ceph作为后端存储

    在ceph监视器上执行 CINDER_PASSWD='cinder1234!'controllerHost='controller'RABBIT_PASSWD='0penstackRMQ' 1.创建p ...

  2. 【科普杂谈】IP地址子网划分

    1.学习子网前的准备知识-什么是数制 现场讲解版 二进制和十进制的关系   二进制和十六进制的关系  16进制的每个位是2进制的4位 F=1111  二进制转16进制,按上面4位一组分开转 2.IP地 ...

  3. linux学习命令收集

    多看看大神的博客  https://blog.csdn.net/tao934798774/article/details/79491951 ip addr   查看ip地址 ifconfig  查看i ...

  4. ZOJ Problem Set - 1006

    注意:A的ascii为65,a为97就行了 其他没什么,略过. 代码参看: http://my.oschina.net/dianpaopao/blog/124545

  5. luoguP2664树上游戏(点分治)

    题目链接:https://www.luogu.org/problem/P2664 题意:给定一颗带点权的树,结点数n<=1e5,点权<=1e5,用s(i,j)表示从i到j的路径上不同点权数 ...

  6. Windows 下部署 hadoop spark环境

    一.先在本地安装jdk 我这里安装的jdk1.8,具体的安装过程这里不作赘述 二.部署安装maven 下载maven安装包,并解压 设置环境变量,MAVEN_HOME=D:\SoftWare\Mave ...

  7. awk 打印从某一列到最后一列的内容

    数据内容来源于  linux history的命令输出 awk命令 history|awk -F " " '{for (i=2;i<=NF;i++)printf(" ...

  8. 将本地镜像上传到Docker镜像仓库

    ⒈在Docker Hub(Docker官方镜像仓库)注册自己的用户名. ⒉在Docker中使用docker login命令登录自己的用户名密码. ⒊使用docker push 镜像名称 上传本地镜像到 ...

  9. java如何防止反编译(转)

    出处: java如何防止反编译 一些防止java代码被反编译的方法 综述(写在前面的废话) Java从诞生以来,其基因就是开放精神,也正因此,其可以得到广泛爱好者的支持和奉献,最终很快发展壮大,以至于 ...

  10. 开发过程遇到的css样式问题记录

    一.移动端 1.部分安卓机圆角border-radius失效,显示为方形状?   background-clip: padding-box; 2.部分安卓机字体图标出现锯齿? 使用iconfont图标 ...