[题解]某模拟题题解



  第一道题还是比较简单,只不过做的时候手贱写错了一个字母,然后活活RE掉了40分

  先处理处最终的图,然后从后往前用并查集完成询问。至于之前的删边可以排个序,

然后建一个长度和它一样的boolean数组标志这条边又没被删,删除的时候就lower_bound

就可以了,只不过注意重复的边。如果这一位上为false(这条边被删掉了)应该往后找到

第一个为true的地方,然后将它改为false



Code:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<fstream>
  4 #include<cstdlib>
  5 #include<queue>
  6 #include<set>
  7 #include<map>
  8 #include<cctype>
  9 #include<algorithm>
 10 #include<cstring>
 11 #include<string>
 12 #include<stack>
 13 using namespace std;
 14 typedef bool boolean;
 15 #define smin(a, b) a = min(a, b)
 16 #define smax(a, b) b = max(a, b)
 17 template<typename T>
 18 inline void readInteger(T& u) {
 19     char x;
 20     while(!isdigit(x = getchar()));
 21     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - ‘0‘);
 22     ungetc(x, stdin);
 23 }
 24
 25 typedef class union_found{
 26     public:
 27         int *f;
 28         union_found():f(NULL) {}
 29         union_found(int points) {
 30             f = new int[(const int)(points + 1)];
 31             for(int i = 0; i <= points; i++)
 32                 f[i] = i;
 33         }
 34         int find(int x) {
 35             if(f[x] != x)    return f[x] = find(f[x]);
 36             return f[x];
 37         }
 38         void unit(int fa, int so) {
 39             int ffa = find(fa);
 40             int fso = find(so);
 41             f[fso] = ffa;
 42         }
 43         boolean connected(int a, int b) {
 44             return find(a) == find(b);
 45         }
 46 }union_found;
 47
 48 typedef class _edge{
 49     public:
 50         int from;
 51         int end;
 52         _edge(const int a = 0, const int b = 0) {
 53             from = min(a, b);
 54             end = max(a, b);
 55         }
 56         boolean operator <(_edge another) const {
 57             if(this->from != another.from)    return this->from < another.from;
 58             return this->end < another.end;
 59         }
 60 }_edge;
 61
 62 typedef class _question{
 63     public:
 64         boolean isCut;
 65         int a;
 66         int b;
 67 }_question;
 68
 69 inline void readQues(_question& que){
 70     int c;
 71     readInteger(c);
 72     if(c == 1)    que.isCut = true;
 73     else que.isCut = false;
 74     readInteger(que.a);
 75     readInteger(que.b);
 76 }
 77
 78 int n, m, q;
 79 union_found uf;
 80 _edge* es;
 81 boolean* enable;
 82 _question *ques;
 83 stack<int> s;
 84
 85 #define MAP_IT multiset<_edge>::iterator
 86
 87 inline void init() {
 88     int lastEdge;
 89     readInteger(n);
 90     readInteger(m);
 91     readInteger(q);
 92     es = new _edge[(const int)(m + 1)];
 93     uf = union_found(n);
 94     ques = new _question[(const int)(q + 1)];
 95     enable = new boolean[(const int)(m + 1)];
 96     lastEdge = m;
 97     memset(enable, true, sizeof(boolean) * (m + 1));
 98     for(int i = 1, a, b; i <= m; i++){
 99         readInteger(a);
100         readInteger(b);
101         es[i] = _edge(a, b);
102     }
103     sort(es + 1, es + m + 1);
104     for(int i = 1; i <= q; i++){
105         readQues(ques[i]);
106         ques[i].a ^= lastEdge;
107         ques[i].b ^= lastEdge;
108         if(ques[i].isCut){
109 //            es.erase(es.lower_bound(_edge(ques[i].a, ques[i].b)));
110             int rank = lower_bound(es + 1, es + m + 1, _edge(ques[i].a, ques[i].b)) - es;
111             while(!enable[rank]) rank++;
112             enable[rank] = false;
113             lastEdge--;
114         }
115     }
116     for(int i = 1; i <= m; i++){
117         if(enable[i])
118             uf.unit(es[i].from, es[i].end);
119     }
120 }
121
122 void solve() {
123     for(int i = q; i > 0; i--){
124         if(ques[i].isCut){
125             uf.unit(ques[i].a, ques[i].b);
126         }else{
127             boolean result = uf.connected(ques[i].a, ques[i].b);
128             if(result)    s.push(1);
129             else s.push(0);
130         }
131     }
132     while(!s.empty()){
133         printf("%d\n", s.top());
134         s.pop();
135     }
136 }
137
138 int main(){
139     freopen("graph.in", "r", stdin);
140     freopen("graph.out", "w", stdout);
141     init();
142     solve();
143     fclose(stdin);
144     fclose(stdout);
145     return 0;
146 }




  第二道相对于第一道题就没有那么友好了,这次真的只能用在线算法,于是我决定用暴力碰碰运气

结果真的AC了。。。(这数据太水,没办法)

  思路很简单,这道题是树,所以,两点之间的连线断开后,就成了两个联通块,然后我给每个连通块

一个编号,然后每次删边就去dfs一遍修改这个值。



Code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<fstream>
  4 #include<cstdlib>
  5 #include<queue>
  6 #include<set>
  7 #include<map>
  8 #include<cctype>
  9 #include<algorithm>
 10 #include<cstring>
 11 #include<string>
 12 using namespace std;
 13 typedef bool boolean;
 14 #define smin(a, b) a = min(a, b)
 15 #define smax(a, b) b = max(a, b)
 16 template<typename T>
 17 inline void readInteger(T& u) {
 18     char x;
 19     while(!isdigit(x = getchar()));
 20     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - ‘0‘);
 21     ungetc(x, stdin);
 22 }
 23
 24 ///Linked Map Template Starts
 25 typedef class Edge{
 26     public:
 27         int next;
 28         int end;
 29         Edge(const int next = 0, const int end = 0):next(next), end(end){    }
 30 }Edge;
 31 typedef class MapManager{
 32     public:
 33         int *h;
 34         Edge* edge;
 35         int ce;
 36         MapManager():h(NULL), edge(NULL), ce(0) { }
 37         MapManager(int point, int edges):ce(0){
 38             h = new int[(const int)(point + 1)];
 39             edge = new Edge[(const int)(edges + 1)];
 40             memset(h, 0, sizeof(int) * (point + 1));
 41         }
 42         inline void addEdge(int from, int end) {
 43             edge[++ce] = Edge(h[from], end);
 44             h[from] = ce;
 45         }
 46 }MapManager;
 47 ///Linked Map Template Ends
 48
 49 int n, q;
 50 MapManager tree;
 51 int* fa;
 52 int* value;
 53 int* types;
 54 int ct;
 55
 56 inline void init() {
 57     ct = 1;
 58     readInteger(n);
 59     readInteger(q);
 60     value = new int[(const int)(n + 1)];
 61     fa = new int[(const int)(n + 1)];
 62     tree = MapManager(n, 2 * n);
 63     types = new int[(const int)(n + 1)];
 64     fill(types + 1, types + n + 1, 1);
 65     for(int i = 1; i <= n; i++)    readInteger(value[i]);
 66     for(int i = 1, a, b; i < n; i++){
 67         readInteger(a);
 68         readInteger(b);
 69         tree.addEdge(a, b);
 70         tree.addEdge(b, a);
 71     }
 72 }
 73
 74 void buildTree(int node, int lastNode){
 75     fa[node] = lastNode;
 76     for(int i = tree.h[node]; i != 0; i = tree.edge[i].next){
 77         int& end = tree.edge[i].end;
 78         if(end == lastNode)    continue;
 79         buildTree(end, node);
 80     }
 81 }
 82
 83 void update(int node, int lastNode, const int newType){
 84     if(fa[node] != lastNode) return;
 85     types[node] = newType;
 86     for(int i = tree.h[node]; i != 0; i = tree.edge[i].next){
 87         int& end = tree.edge[i].end;
 88         if(end == lastNode)    continue;
 89         update(end, node, newType);
 90     }
 91 }
 92
 93 int lastans;
 94
 95 inline void solve() {
 96     buildTree(1, 0);
 97     for(int i = 1, c, a, b; i <= q; i++){
 98         readInteger(c);
 99         readInteger(a);
100         readInteger(b);
101         a ^= lastans;
102         b ^= lastans;
103         int s;
104         switch(c){
105         case 1:
106             if(fa[a] == b){
107                 s = a;
108             }else{
109                 s = b;
110             }
111             fa[s] = 0;
112             update(s, 0, ++ct);
113             break;
114         case 2:
115             if(types[a] == types[b]){
116                 lastans = value[a] * value[b];
117             } else {
118                 lastans = value[a] + value[b];
119             }
120             printf("%d\n", lastans);
121             break;
122         case 3:
123             value[a] = b;
124             break;
125         default:
126 //            throw c;
127             break;
128         }
129     }
130 }
131
132 int main(){
133     freopen("tree.in", "r", stdin);
134     freopen("tree.out", "w", stdout);
135     init();
136     solve();
137     return 0;
138 }




  第三题,也是最简单的一道,直接Tarjan搜强连通分量不解释

Code

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<fstream>
  4 #include<cstdlib>
  5 #include<queue>
  6 #include<set>
  7 #include<map>
  8 #include<stack>
  9 #include<cctype>
 10 #include<algorithm>
 11 #include<cstring>
 12 #include<string>
 13 using namespace std;
 14 typedef bool boolean;
 15 #define smin(a, b) a = min(a, b)
 16 #define smax(a, b) b = max(a, b)
 17 template<typename T>
 18 inline void readInteger(T& u) {
 19     char x;
 20     while(!isdigit(x = getchar()));
 21     for(u = x - ‘0‘; isdigit((x = getchar())); u = (u << 3) + (u << 1) + x - ‘0‘);
 22     ungetc(x, stdin);
 23 }
 24 ///Linked Map Template Starts
 25 typedef class Edge{
 26     public:
 27         int next;
 28         int end;
 29         Edge(const int next = 0, const int end = 0):next(next), end(end){    }
 30 }Edge;
 31 typedef class MapManager{
 32     public:
 33         int *h;
 34         Edge* edge;
 35         int ce;
 36         MapManager():h(NULL), edge(NULL), ce(0) { }
 37         MapManager(int point, int edges):ce(0){
 38             h = new int[(const int)(point + 1)];
 39             edge = new Edge[(const int)(edges + 1)];
 40             memset(h, 0, sizeof(int) * (point + 1));
 41         }
 42         inline void addEdge(int from, int end) {
 43             edge[++ce] = Edge(h[from], end);
 44             h[from] = ce;
 45         }
 46 }MapManager;
 47 ///Linked Map Template Ends
 48
 49 MapManager g;
 50 long long result;
 51
 52 stack<int> s;
 53 boolean* visited;
 54 boolean* inStack;
 55 int counter;
 56 int *visitID;
 57 int *exitID;
 58
 59 inline void getMap(int end){
 60     int c_m = 0;
 61     int node;
 62     do{
 63         node = s.top();
 64         s.pop();
 65         inStack[node] = false;
 66         c_m++;
 67     }while(node != end);
 68     result += c_m * 1LL * (c_m - 1) / 2;
 69 }
 70
 71 void Tarjan(int node){
 72     visited[node] = true;
 73     visitID[node] = exitID[node] = ++counter;
 74     s.push(node);
 75     inStack[node] = true;
 76     for(int i = g.h[node]; i != 0; i = g.edge[i].next){
 77         int e = g.edge[i].end;
 78         if(!visited[e]) {
 79             Tarjan(e);
 80             smin(exitID[node], exitID[e]);
 81         } else if(inStack[e]) {
 82             smin(exitID[node], visitID[e]);
 83         }
 84     }
 85     if(visitID[node] == exitID[node])
 86         getMap(node);
 87 }
 88
 89 int n;
 90 int m;
 91
 92 inline void init() {
 93     readInteger(n);
 94     readInteger(m);
 95     g = MapManager(n, m);
 96     visited = new boolean[(const int)(n + 1)];
 97     inStack = new boolean[(const int)(n + 1)];
 98     visitID = new int[(const int)(n + 1)];
 99     exitID = new int[(const int)(n + 1)];
100     memset(visited, false, sizeof(boolean) * (n + 1));
101     memset(inStack, false, sizeof(boolean) * (n + 1));
102     for(int i = 1, a, b; i <= m; i++) {
103         readInteger(a);
104         readInteger(b);
105         g.addEdge(a, b);
106     }
107 }
108
109 inline void solve() {
110     for(int i = 1; i <= n; i++) {
111         if(!visited[i])
112             Tarjan(i);
113     }
114     cout<<result;
115 }
116
117 int main(){
118     freopen("logic.in", "r", stdin);
119     freopen("logic.out", "w", stdout);
120     init();
121     solve();
122     return 0;
123 } 
时间: 2024-11-10 08:35:54

[题解]某模拟题题解的相关文章

10.9 guz模拟题题解

感谢@guz 顾z的题题解 考试共三道题,其中 第一题help共10个测试点,时间限制为 1000ms,空间限制为 256MB. 第二题escape共20个测试点,时间限制为1000ms2000ms,空间限制1MB16MB. 第三题cure共20个测试点,时间限制为 1000ms,空间限制为 256MB. PS:题目背景与题目本身无关,可跳过 help 题目背景 在梦中,王 小 呆 到了一个神秘的地方.这里是昆虫王国!国王见王 小 呆 好生俊俏,便给了他一杯昆虫国的老白干.王 小 呆一口下肚,突

[总结+题解]NOIP2015模拟题2

// 此博文为迁移而来,写于2015年7月22日,不代表本人现在的观点与看法.原始地址:http://blog.sina.com.cn/s/blog_6022c4720102w72i.html 1.总结 向总表示今天的题目简单些,恩我觉得我又单纯了.今天的分数略低啊,第三题的动规只有10分,第一题的暴力也TLE了一堆,最后就剩下个150分了. 2.题解 T1 坐船问题(TAG:结论题) 简直就是一道结论题啊!这道题不存在什么算法.最开始想到的是二分图匹配,但是过于繁琐,而且已经证出存在反例.首先

[题解]某模拟题(USACO月赛部分题+noip2005部分题)

题目描述 农场上有N(1 <= N <= 50,000)堆草,放在不同的地点上.FJ有一辆拖拉机,也在农场上.拖拉机和草堆都表示为二维平面上的整数坐标,坐标值在1..1000的范围内.拖拉机的初始位置与所有草堆不同. FJ开拖拉机时,只能平行于坐标轴(即东.南.西.北四个方向),而且每次开动的一段必须是整数长度.例如,他可以向北开2个单位长度,然后向东开3个单位长度.拖拉机不能开到草堆的位置. 请帮助FJ计算出最少要移动多少个草堆,他才能将拖拉机开回坐标原点. 拖拉机可以开到1..1000之外

[题解]noip杂题题解

这道题没有什么可说的,先统计,然后几次快排,答案就出来了 Code(整齐但不简洁的代码) 1 #include<iostream> 2 #include<cstdio> 3 #include<fstream> 4 #include<cstring> 5 #include<queue> 6 #include<algorithm> 7 using namespace std; 8 typedef bool boolean; 9 templ

cdoj 25 点球大战(penalty) 模拟题

点球大战(penalty) Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.uestc.edu.cn/#/problem/show/25 Description 在足球比赛中,有不少赛事,例如世界杯淘汰赛和欧洲冠军联赛淘汰赛中,当比赛双方经过正规比赛和加时赛之后仍然不分胜负时,需要进行点球大战来决定谁能够获得最终的胜利.点球大战的规则非常简单,两方轮流派出球员罚点球,每方各罚5个.当5轮点球结束以后如果仍然不分胜负,则进入一轮定胜

PAT甲题题解-1095. Cars on Campus(30)-(map+树状数组,或者模拟)

题意:给出n个车辆进出校园的记录,以及k个时间点,让你回答每个时间点校园内的车辆数,最后输出在校园内停留的总时间最长的车牌号和停留时间,如果不止一个,车牌号按字典序输出. 几个注意点: 1.如果一个车连续多次进入,只取最后一个 2.如果一个车连续多次出去,只取第一个 3.一个车可能出入校园内好几次,停留时间取总和 实际上题目就是让我们求某个时间段内的车辆总和,时间段其实就相当于一个区间,区间求和的话,很快就联想到树状数组和线段树.然而怎么将时间段和区间联系起来呢,那就存储出现在记录和询问里的所有

PAT甲题题解-1088. Rational Arithmetic (20)-模拟分数计算

输入为两个分数,让你计算+,-,*,\四种结果,并且输出对应的式子,分数要按带分数的格式k a/b输出如果为负数,则带分数两边要有括号如果除数为0,则式子中的结果输出Inf模拟题最好自己动手实现,考验细节处理,其它没啥好说的. #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; long long numerato

2018-10-25 模拟测试题解

目录 问题 A: 魏传之长坂逆袭 题目描述 输入 输出 样例输入 样例输出 题解 问题 B: 蜀传之单刀赴会 题目描述 [问题描述] 输入 输出 样例输入 样例输出 题解 问题 C: 吴传之火烧连营 [题目背景] [问题描述] 输入 输出 样例输入 样例输出 [样例解释] [数据规模和约定] 题解 本篇题解也发表于zwcblog作者是同一个人 问题 A: 魏传之长坂逆袭 题目描述 众所周知,刘备在长坂坡上与他的一众将领各种开挂,硬生生从曹操手中逃了出去,随后与孙权一起火烧赤壁.占有荆益.成就霸业

lzoi模拟赛题解

A题:签到题原题:mtoi 联赛 的A题定位:真.签到题(普及B题或者提高d1A题)考点:选手的基本数学能力思维难度:提高-代码难度:普及A题 题解:80%:暴力枚举100%:注意到(a xor b)<=(a+b),于是把所有的数异或起来即可. B题:送分题原题:[多省省队联测]d2A:皮配定位:一道联赛d1B题,考察了选手的基本功.送了选手70分.把70%的2种做法扩展可以得到正解考点:多种背包dp,计数思维难度:提高代码难度:提高+ 前面的几个数据可以暴力枚举解决.50%的数据:考虑dp.设