C. Destroying Array 并查集/线段树 Intel Code Challenge Elimination Round (Div. 1 + Div. 2, combined)

题目大意就是给一个初始数组,每次删除一个点,问你剩下的连续的那些点中,最大的和是多少

2种做法

第一种是离线并查集  (这里是不会用那个res[]数组,将子的权值挪给父亲那里.

第二种是线段树区间合并。(练手

///线段树

  1 #include <algorithm>
  2 #include <stack>
  3 #include <istream>
  4 #include <stdio.h>
  5 #include <map>
  6 #include <math.h>
  7 #include <vector>
  8 #include <iostream>
  9 #include <queue>
 10 #include <string.h>
 11 #include <set>
 12 #include <cstdio>
 13 #define FR(i,n) for(int i=0;i<n;i++)
 14 #define MAX 2005
 15 #define mkp pair <int,int>
 16 using namespace std;
 17 //#pragma comment(linker, "/STACK:10240000000,10240000000")
 18 const int maxn = 1e5+50;
 19 typedef long long ll;
 20 const int  inf = 0x3fffff;
 21 void read(ll  &x) {
 22     char ch; bool flag = 0;
 23     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == ‘-‘)) || 1); ch = getchar());
 24     for (x = 0; isdigit(ch); x = (x << 1) + (x << 3) + ch - 48, ch = getchar());
 25     x *= 1 - 2 * flag;
 26 }
 27 int n;
 28 ll val[maxn];
 29 struct tree {
 30     //int id;
 31     int l, r;
 32     long long  ll, rr;
 33     long long  maxx;
 34     int len;
 35     bool flag;
 36 }Tree[maxn<<3];
 37
 38 ll query[maxn];
 39
 40
 41 void build(int l, int r, int id)
 42 {
 43     Tree[id].flag = true;
 44     Tree[id].l = l;
 45     Tree[id].r = r;
 46     Tree[id].len=r-l+1;
 47     if (l == r)
 48     {
 49         Tree[id].maxx = Tree[id].ll=Tree[id].rr=val[l];
 50         return;
 51     }
 52     int mid = (l + r) / 2;
 53     build(mid + 1, r, 2 * id + 1);
 54     build(l, mid, 2 * id);
 55     Tree[id].maxx = Tree[id * 2].maxx + Tree[id * 2 + 1].maxx;
 56     Tree[id].ll = Tree[id].rr = Tree[id].maxx;
 57 }
 58
 59
 60
 61 void pushup(int id)
 62 {
 63     Tree[id].ll = Tree[id * 2].ll;
 64     if (Tree[id * 2].flag)Tree[id].ll += Tree[id * 2 + 1].ll;
 65
 66     Tree[id].rr = Tree[id * 2 + 1].rr;
 67     if (Tree[id * 2 + 1].flag)Tree[id].rr += Tree[id * 2].rr;
 68     Tree[id].maxx = max(Tree[id * 2].maxx,Tree[id * 2 + 1].maxx);
 69     Tree[id].maxx = max(Tree[id].maxx, Tree[id * 2+1].ll + Tree[id * 2 ].rr);
 70     if (!Tree[id * 2].flag || !Tree[id * 2 + 1].flag)Tree[id].flag = 0;
 71 }
 72 void repair(int id, int pos)
 73 {
 74    // cout<<id<<endl;
 75     if (Tree[id].l == pos && Tree[id].r == pos)
 76     {
 77         //printf("%d&&&\n",Tree[id].l);
 78         Tree[id].flag = 0;
 79         Tree[id].ll = Tree[id].rr =Tree[id].maxx =0;
 80     }
 81     else
 82     {
 83         int mid = (Tree[id].l + Tree[id].r) / 2;
 84         if (pos > mid) {
 85             repair(id * 2 + 1, pos);
 86         }
 87         else {
 88             repair(id * 2, pos);
 89         }
 90         pushup(id);
 91     }
 92 }
 93 int main() {
 94     cin>>n;
 95     for (int i = 1; i <= n; i++)read(val[i]);
 96     for (int i = 1; i <= n; i++)read(query[i]);
 97
 98     build(1, n, 1);
 99     for (int i = 1; i  <= n; i++ )
100     {
101         repair(1, query[i]);
102         cout << Tree[1].maxx << endl;
103     }
104     return 0;
105 }

///并查集

 1 #include <algorithm>
 2 #include <stack>
 3 #include <istream>
 4 #include <stdio.h>
 5 #include <map>
 6 #include <math.h>
 7 #include <vector>
 8 #include <iostream>
 9 #include <queue>
10 #include <string.h>
11 #include <set>
12 #include <cstdio>
13 #define FR(i,n) for(int i=0;i<n;i++)
14 #define MAX 2005
15 #define mkp pair <int,int>
16 using namespace std;
17 //#pragma comment(linker, "/STACK:10240000000,10240000000")
18 const int maxn = 1e6+4;
19 typedef long long ll;
20 const int  inf = 0x3fffff;
21 void read(ll  &x) {
22     char ch; bool flag = 0;
23     for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == ‘-‘)) || 1); ch = getchar());
24     for (x = 0; isdigit(ch); x = (x << 1) + (x << 3) + ch - 48, ch = getchar());
25     x *= 1 - 2 * flag;
26 }
27
28
29 ll res[maxn],arr[maxn],fa[maxn];
30 ll pos[maxn];
31 bool vis[maxn];
32 ll ans[maxn];
33
34
35 ll fin(ll x)
36 {
37     if(x==fa[x])return x;
38     else {
39         return fa[x]=fin(fa[x]);
40     }
41 }
42
43 void unite(ll x,ll y)
44 {
45     x=fin(x),y=fin(y);
46     if(x==y)return ;
47     else {
48         fa[y]=x;
49         res[x]+=res[y];
50     }
51 }
52
53 int main() {
54     ll n;
55     read(n);
56     for(int i=1;i<=n;i++)read(arr[i]);
57     for(int i=1;i<=n;i++)
58     {
59         read(pos[i]);
60         res[pos[i]]=arr[pos[i]];
61         fa[i]=i;
62         vis[i]=1;
63     }
64     for(int i=n;i>=2;i--)
65     {
66         ll tmp =pos[i];
67         if(pos[i]!=n)
68         {
69             if(!vis[tmp+1])
70             {
71                 unite(tmp,tmp+1);
72             }
73
74         }
75             if(tmp>=2&&!vis[tmp-1])
76             {
77                 unite(tmp,tmp-1);
78             }
79         ll temp = res[tmp];
80         ans[i]=max(ans[i+1],temp);
81         vis[tmp]=false;
82     }
83     for(int i=2;i<=n+1;i++)printf("%lld\n",ans[i]);
84     return 0;
85 }

原文地址:https://www.cnblogs.com/DreamKill/p/9427830.html

时间: 2024-10-31 04:46:28

C. Destroying Array 并查集/线段树 Intel Code Challenge Elimination Round (Div. 1 + Div. 2, combined)的相关文章

Intel Code Challenge Elimination Round (Div.1 + Div.2, combined) C. Destroying Array -- 逆向思维

原题中需要求解的是按照它给定的操作次序,即每次删掉一个数字求删掉后每个区间段的和的最大值是多少. 正面求解需要维护新形成的区间段,以及每段和,需要一些数据结构比如 map 和 set. map<int, LL>interval2Sum来维护区间段(u->v),mulitset<LL>sum 来维护最大值.那么每次删除操作后,都需要去interval2Sum中找到对应区间,然后erase掉, 重新生成left -> delId -> right两个区间段,最后在ma

Intel Code Challenge Elimination Round (Div.1 + Div.2, combined)C. Destroying Array(想法题)

传送门 Description You are given an array consisting of n non-negative integers a1, a2, ..., an. You are going to destroy integers in the array one by one. Thus, you are given the permutation of integers from 1 to n defining the order elements of the ar

UVA1455 - Kingdom(并查集 + 线段树)

UVA1455 - Kingdom(并查集 + 线段树) 题目链接 题目大意:一个平面内,给你n个整数点,两种类型的操作:road x y 把city x 和city y连接起来,line fnum (浮点数小数点一定是0.5) 查询y = fnum这条直线穿过了多少个州和city.州指的是连通的城市. 解题思路:用并查集记录城市之间是否连通,还有每一个州的y的上下界.建立坐标y的线段树,然后每次运行road操作的时候,对范围内的y坐标进行更新:更新须要分三种情况:两个州是相离,还是相交,还是包

bzoj2733 [ HNOI2012 ] -- 并查集+线段树合并

用并查集记录每个联通块的根节点,每个联通块建一棵线段树,合并时合并线段树就可以了. 代码: 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 using namespace std; 5 #define N 100010 6 struct node{ 7 int l,r,x; 8 }c[N*20]; 9 int i,j,k,n,m,l,r,a[N],x,y,Rt[N],Num,b[N],f[N],

uva 1455 - Kingdom(并查集+线段树)

题目链接:uva 1455 - Kingdom 题目大意:平面上又n个城市,初始时城市之间没有任何双向道路相连,要求一次执行指令. road A B :在城市A和城市B之间连接一条双向道路 line C:询问一条y=C的水平线上穿过多少州和这些州总共有多少城市. 一个联通分量算一个州,C保证为小数部分为0.5的实数. 解题思路:线段树维护每个位置上州和城市的个数,并查集维护哪些城市属于同一个州,并且要记录这些州上下范围.每次新建一条道路,要相应根据两个州的y坐标范围对线段树进行维护. #incl

[BZOJ2733] [HNOI2012]永无乡(并查集 + 线段树合并)

传送门 一看到第k大就肯定要想到什么权值线段树,主席树,平衡树之类的 然后就简单了 用并查集判断连通,每个节点建立一颗权值线段树,连通的时候直接合并即可 查询时再二分递归地查找 时间复杂度好像不是很稳定...但hzwer都用这种方法水过.. 正解好像是平衡树+启发式合并,以后学TT #include <cstdio> #include <iostream> #define N 100001 int n, m, q, cnt; int a[N], f[N], sum[N * 20],

并查集 + 线段树 LA 4730 Kingdom

题目传送门 题意:训练指南P248 分析:第一个操作可以用并查集实现,保存某集合的最小高度和最大高度以及城市个数.运用线段树成端更新来统计一个区间高度的个数,此时高度需要离散化.这题两种数据结构一起使用,联系紧密. #include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; const int M = 3 * N; const int INF = 0x3f3f3f3f; struct Point { int x, y

uvalive 4730王国kingdom(并查集+线段树)

 题意:有T组测试数据,每组数据的N表示有N个城市,接下来的N行里每行给出每个城市的坐标(0<=x,y<=1000000),然后有M(1<M<200000)个操作,操作有两类,(1)"road A B",表示将城市A和城市B通过一条道路连接,如果A和B原来属于不同的城市群,经过这个操作,A和B就在一个城市群里了,保证每条道路不会和其他道路相交(除了端点A和B).(2)"line C",表示查询当穿过y=C的直线,有多少个城市群.这几个城市

BZOJ 3319 黑白树 并查集+线段树

这这这这这这什么毒瘤题!!!!!!!!!!!!!!!!!!!!!!!!!!!! 卡LCT(优秀的LCT由于是均摊本身就带着2,3的常数在,而且这道题对于LCT标记十分难维护,又得乘上4,5然后就炸了),卡树剖,卡正解,但是暴力能A!!!!!!!!!!!!!!!!!!!!!! 所谓正解就是线段树为护dfs序+并查集删点去重,这东西在每个点一秒的时候都过不了Po姐都虚. 但是我在网上看到一个大佬有一个神思路A掉了 下面是我改过之后的的TLE程序 #include<cstdio> #include&