VK Cup 2012 Qualification Round 2 C. String Manipulation 1.0 线段树 or 树状数组+二分
http://codeforces.com/problemset/problem/159/C
题意:
给你一个字符串s,给出一个数k,k倍的s串组成新串str。然后给出n个操作,每个操作对应着pi,ci意思是将第pi个字符ci从str中删除,求最后得到的字符串。
思路:
首先我想到的是利用vector里面的erase快速的删除,开一个vc[26]来存取每个字符然后模拟删除过程,才开始自己一维erase的时间复杂度为O(1)如果这样肯定不会超时,结果事与愿违果真TLE了。问了问别人晚会上搜了搜原来erase函数的平均复杂度竟然是O(n)这样固然超时,可是看了看AC的代码里面也有用vector + erase写的,只是标记了以下过的。其实这不是正解。
正解在此,看了以下官方的解体报告,开一个26个线段树,于是就往线段树方向思考。果然,我们只要开一个二位的线段树val[27][4*N]然后没出现相应的字符我们就将其插入,线段树记录区间满足条件的个数。然后每次删除时我们只要利用线段树的查询第整个区间里面的第几个来删除就好了。这里在执行删除与更新时弄混了,导致在第三组数据上错了好多次,吐槽以下给的大数据都带省略号的怎么改啊,悲粹啊..
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string>#define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b)#define ll long long #define inf 0x7f7f7f7f #define MOD 1073741824 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 150 #define N 200007 using namespace std; //freopen("data.in","r",stdin);int pos[27][N]; int val[27][N*4]; char str[107]; int num[27]; int lp;void pushup(int rt,int mk){val[mk][rt] = val[mk][rt<<1] + val[mk][rt<<1|1]; } void update(int mk,int d,int sc,int l,int r,int rt){if (l == r){val[mk][rt] = sc;return ;}int m = (l + r)>>1;if (d <= m) update(mk,d,sc,lc);else update(mk,d,sc,rc);pushup(rt,mk); } //注意modify与update的区别,才开始搞混了。 void modify(int mk,int d,int sc,int l,int r,int rt){if (l == r){val[mk][rt] = sc;return ;}int m = (l + r)>>1;if (d <= val[mk][rt<<1]) modify(mk,d,sc,lc);else{d -= val[mk][rt<<1];modify(mk,d,sc,rc);}pushup(rt,mk); } int query(int mk,int d,int l,int r,int rt){if (l == r){lp = l;//记录删除的位置return pos[mk][l];//返回其坐标, }int m = (l + r)>>1;if (d <= val[mk][rt<<1]) return query(mk,d,lc);else{d -= val[mk][rt<<1];return query(mk,d,rc);} } int main(){//freopen("data.in","r",stdin);int n,i,j;int k;n = 200001;scanf("%d%s",&k,str);int len = strlen(str);int p = 0;int no = 0;CL(val,0); CL(num,0);for (i = 0; i < k; ++i){for (j = 0; j < len; ++j){int mk = str[j] - 'a';pos[mk][++num[mk]] = p++;//记录每个点的下标,方便用于按下标从小到大排序update(mk,num[mk],1,1,n,1);no++;}}char tp[3];int q,d;scanf("%d",&q);while (q--){scanf("%d%s",&d,tp);int mk = tp[0] - 'a';modify(mk,d,0,1,n,1);no--;}int pp;int Lp;while (no--){int MIN = inf;for (i = 0; i < 26; ++i){if (val[i][1] != 0){int tmp = query(i,1,1,n,1);if (MIN > tmp){MIN = tmp;pp = i;Lp = lp;}}}update(pp,Lp,0,1,n,1);printf("%c",pp + 'a');}printf("\n");return 0; }
第二种正解就是树状数组+二分了。
其实思路差不多,树状数组果然比线段树代码量少的多啊。我们把整个str分为26个应为字符对应的位置,然后每次删除时,二分找到第d个然后将其删除,二分中求和利用树状数组。然后hash表示每个位置是否被删除了,然后输出即可。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string>#define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b)#define ll long long #define inf 0x7f7f7f7f #define MOD 1073741824 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 150 #define N 200007 using namespace std; //freopen("data.in","r",stdin); int len; bool hash[N]; struct BIT{#define lowbit(x) ((x) & (-x));int tree[N];void init(){CL(tree,0);}inline void update(int x,int val){while (x <= len){tree[x] += val;x += lowbit(x);}}inline int query(int x){int sum = 0;while (x > 0){sum += tree[x];x -= lowbit(x);}return sum;} }a[27];char str[105];int main(){// freopen("data.in","r",stdin);int i,j;int k;scanf("%d%s",&k,str);int L = strlen(str);len = L*k;int pos = 0;for (i = 0 ; i < 26; ++i) a[i].init();for (i = 0; i < k; ++i){for (j = 0; j < L; ++j){a[str[j] - 'a'].update(++pos,1);}}CL(hash,0);int q,d;char ask[3];scanf("%d",&q);while (q--){scanf("%d%s",&d,ask);int mk = ask[0] - 'a';int ans = 0;int l = 1, r = len;while (l <= r){int m = (l + r)>>1;int tmp = a[mk].query(m);if (tmp >= d){r = m - 1;// 注意这里要r = m - 1 是因为1 到 m里面不是每一个都满足条件的只是和等于dans = m;}else if (tmp < d){l = m + 1;}}hash[ans] = true;a[mk].update(ans,-1);}pos = 0;for (i = 0 ; i < k; ++i){for (j = 0; j < L; ++j){if (!hash[++pos]) printf("%c",str[j]);}}printf("\n");return 0; }
VK Cup 2012 Qualification Round 2 C. String Manipulation 1.0 线段树 or 树状数组+二分相关推荐
- VK Cup 2012 Qualification Round 2 C. String Manipulation 1.0 字符串模拟
C. String Manipulation 1.0 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 codeforces.com/problemset/pr ...
- VK Cup 2015 - Qualification Round 1 A. Reposts(树)
传送门 Description One day Polycarp published a funny picture in a social network making a poll about t ...
- VK Cup 2012 Round 1 D. Distance in Tree (树形dp)
题目:http://codeforces.com/problemset/problem/161/D 题意:给你一棵树,问你两点之间的距离正好等于k的有多少个 思路:这个题目的内存限制首先大一倍,他有5 ...
- 【树形dp】VK Cup 2012 Round 1 D. Distance in Tree
统计树中长度为K的路径条数. 用f[u][k]表示从u结点的子树中出发,终止于u结点的长度为k的路径条数. 边dp边统计答案.为了防止重复统计,在枚举子节点的时候,先将该子节点和当前u结点(和前面已经 ...
- Facebook Hacker Cup 2016 Qualification Round 解题报告
Boomerang Constellations 题意: 给定N≤2×103个点,求满足dis(x,y)=dis(y,z)的三元组(x,y,z)个数,(x,y,z)与(z,y,x)被认为是相同的给定N ...
- codeforces VK Cup 2018 - Wild-card Round 1 (unofficial unrated mirror)
开开心心的打开codeforces, 本来打算疯狂AC一波,结果开了这一场,进去一看题好简单呀,火速交一发,结果交第二题的时候提示不让我交了??????????? 提示每种语言只能AC一道题,ok,难 ...
- Codeforces Round #623 (Div. 2, based on VK Cup 2019-2020 - Elimination Round, Engine) C. Restoring
C. Restoring Permutation time limit per test1 second memory limit per test256 megabytes inputstandar ...
- Codeforces Round #623 (Div. 2, based on VK Cup 2019-2020 - Elimination Round, Engine) A Dead Pixel
讨论坏点的左右上下的矩形大小. #include <bits/stdc++.h> using namespace std; int main() {int t;cin >> t ...
- Codeforces Round #439 (Div. 2) E. The Untended Antiquity (hash+数状数组)
这个题,做出来的人很多,我感觉是数据不够强,我看了很多人的代码直接暴力也能过了,直接暴力如果数据够强的话肯定是时间超限,边缘数据不够强.如果和上次一样估计很多人的E会GG.我看到一位OIdalao的代 ...
最新文章
- C#中ToString()格式大全(转)
- Jmeter内置函数功能(五)
- linux deepin使用FFmpeg处理视频格式、尺寸、播放速度
- 学习3D游戏开发进阶之路
- java.lang.math.abs_java.lang.StrictMath.abs(int a)方法实例
- 如何快速通过全国计算机等级考试【二级三级】(干货文章)
- EF 使用遇到过的错误记录备忘
- 【Xamarin报错】visual studio android 模拟器部署卡住
- [转]Time Tracker Starter Kit 简介
- 小峰servlet/jsp(4)EL表达式
- 信息系统项目管理师计算题(三点估算)
- 关于power apps
- 机器学习笔记 - 什么是高斯混合模型(GMM)?
- java查看微信付款记录怎么查_微信支付java版本之查询订单
- json与xml的相互转换
- PDF编辑方法,PDF文件怎么修改内容
- ROUGE: A Package for Automatic Evaluation of Summaries
- java swing paint_Java Paint未在Swing中绘制
- linux wifi repeater,WHR-G300N V2 上使用 OpenWrt 构建 WDS 无线网络扩展
- Linux:安装npm
热门文章
- 如何判断浏览器/标签是否有效[重复]
- 除了允许变量被const函数修改之外,'mutable'关键字是否有任何其他用途?
- C#中的多线程:如何将函数名称传递给另一个函数来启动新线程?
- jquery上传图片_MVC 上传图片,裁剪头像
- 10A 的GROUP和CUI使用
- c 语言 循环判断语句,C值循环语句(七)
- java 协议开发_用Java的NIO开发网络协议
- vbs按钮传递过程_iOS面试题:事件传递和响应机制
- python网站设计中接口的作用_python接口自动化(三)--如何设计接口测试用例(详解)...
- 实验3-3 比较大小 (10 分)