Eyjafjalla
Eyjafjalla
題意:
有一棵樹(shù),每個(gè)點(diǎn)都有自己的溫度,保證根節(jié)點(diǎn)1溫度最高,離根節(jié)點(diǎn)越遠(yuǎn)溫度越低。現(xiàn)在在一個(gè)節(jié)點(diǎn)x爆發(fā)病毒,病毒的適宜溫度是[l,r],這個(gè)病毒可以傳播到溫度在[l,r]的臨近點(diǎn)上,問(wèn)有多少個(gè)點(diǎn)被感染了
題解:
題目中說(shuō)點(diǎn)的溫度離根節(jié)點(diǎn)越遠(yuǎn),溫度越低,也就是說(shuō)子樹(shù)內(nèi)的溫度都要比其根節(jié)點(diǎn)低。現(xiàn)在我們要找與x相連的且溫度在[l,r]的節(jié)點(diǎn),他們是連續(xù)的。我們可以這樣,從x向上找父親節(jié)點(diǎn)fa(找fa用倍增),越往上找,點(diǎn)的溫度必然越高,我們找最后一個(gè)溫度在[l,r]范圍內(nèi)的fa,這樣以fa為根的子樹(shù)的溫度都是小于r的,且都是連續(xù)的,也就是dfs序是相連的,左右區(qū)間就是in[fa],out[fa],答案的節(jié)點(diǎn)必然在這里面,現(xiàn)在我們要找in[fa],out[fa]范圍內(nèi)溫度在[l,r]的。二維數(shù)點(diǎn)問(wèn)題,可以用cdq(我用的這個(gè)),也可以用樹(shù)狀數(shù)組等。詳細(xì)看代碼。
不會(huì)二維數(shù)點(diǎn)的可以看這個(gè) P2163 [SHOI2007]園丁的煩惱
他們有用主席樹(shù)做的,這個(gè)題方法很多。
代碼:
// Problem: Eyjafjalla // Contest: NowCoder // URL: https://ac.nowcoder.com/acm/contest/11260/E // Memory Limit: 1048576 MB // Time Limit: 2000 ms // Data:2021-08-14 13:08:18 // By Jozky#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; template <typename T> inline void read(T& x) {T f= 1;x= 0;char ch= getchar();while (0 == isdigit(ch)) {if (ch == '-')f= -1;ch= getchar();}while (0 != isdigit(ch))x= (x << 1) + (x << 3) + ch - '0', ch= getchar();x*= f; } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime= clock();freopen("in.txt", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn= 5e6 + 9; vector<int> vec[maxn]; int in[maxn], out[maxn]; int fa[200000][30], dep[maxn]; int lg[maxn]; int num[maxn]; int A[maxn]; int tim=0; inline void dfs(int x, int fa,int w) {in[x]= ++tim;num[tim]= x;for (int i= 0; i < vec[x].size(); i++) {int v= vec[x][i];if (v == fa)continue; //防止又從子節(jié)點(diǎn)找回去dfs(v, x, tim);}out[x]=++tim; } void dfs(int now, int fath) //初始化深度及祖祖輩輩 {dep[now]= dep[fath] + 1;fa[now][0]= fath;for (int i= 1; (1 << i) <= dep[now]; i++)fa[now][i]= fa[fa[now][i - 1]][i - 1]; //前文的遞推式for (int i= 0; i < vec[now].size(); i++) {int v= vec[now][i];if (v != fath)dfs(v, now);} }int solve(int x, int l, int r) {//printf("x=%d\n",x);for (int i= lg[dep[x]]; i >= 0; i--) //倍增一起往上跳{if (A[fa[x][i]] <= r&&A[fa[x][i]]>=l) {x= fa[x][i];solve(x,l,r);}}return x; } struct st {int x, y, typ, add, id, ans; } s[maxn], ce[maxn]; int n, m, x, y, tot, a, b, c, d, ans[maxn]; void add(int x, int y, int typ, int add, int id, int ans) {s[++tot]= (st){x, y, typ, add, id, ans}; } bool com(st a, st b) {if (a.x == b.x)if (a.y == b.y)return a.typ < b.typ;elsereturn a.y < b.y;return a.x < b.x; } void cdq(int l, int r) {if (l == r)return;int mid= (l + r) >> 1;cdq(l, mid);cdq(mid + 1, r);int le= l, re= mid + 1, pos= 0, ans= 0;while (le <= mid || re <= r) {if (re > r || (le <= mid && s[le].y <= s[re].y)) {if (s[le].typ == 1)++ans;ce[++pos]= s[le++];}else {if (s[re].typ == 2)s[re].ans+= ans;ce[++pos]= s[re++];}}for (int i= 1; i <= pos; i++)s[l + i - 1]= ce[i]; }int main() {rd_test();int n;cin >> n;lg[0]= -1;for (int i= 1; i <= n; i++)lg[i]= lg[i >> 1] + 1;for (int i= 1; i < n; i++) {int u, v;scanf("%d%d", &u, &v);vec[u].push_back(v);vec[v].push_back(u);}dfs(1, 0, 0);dfs(1, 0);for (int i= 1; i <= n; i++) {scanf("%d", &A[i]);add(in[i], A[i], 1, 0, 0, 0);add(out[i], A[i], 1, 0, 0, 0);}int m;cin >> m;int x, l, r;for (int i= 1; i <= m; i++) {scanf("%d%d%d", &x, &l, &r);if(A[x]<l||A[x]>r){a=0,b=0,c=0,d=0; }else {int rt= solve(x, l, r);// cout<<"rt"<<rt<<endl;a= in[rt];b= l;c= out[rt];d= r;} add(a - 1, b - 1, 2, 1, i, 0);add(c, d, 2, 1, i, 0);add(a - 1, d, 2, -1, i, 0);add(c, b - 1, 2, -1, i, 0);}sort(s + 1, s + 1 + tot, com);cdq(1, tot);for (int i= 1; i <= tot; i++)if (s[i].typ == 2)ans[s[i].id]+= s[i].add * s[i].ans;for (int i= 1; i <= m; i++)printf("%d\n", ans[i]/2);//Time_test(); }總結(jié)
以上是生活随笔為你收集整理的Eyjafjalla的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: PRML笔记 第一章 Introduct
- 下一篇: P2163 [SHOI2007]园丁的烦