【GDOI2016模拟3.11】历史
Description
Input
Output
Sample Input
3 7
R 0 1
T 0 1 1
K 1
R 0 1
T 0 1 1
R 0 1
T 0 2 1
Sample Output
Y
N
Y
Data Constraint
.
.
.
.
.
分析
【簡(jiǎn)潔且能夠處理詢(xún)問(wèn)也強(qiáng)制在線的情況】
30%做法:暴力存下每次的并查集。復(fù)雜度O(nm)。
70%做法:熟悉數(shù)據(jù)結(jié)構(gòu)的同學(xué)應(yīng)該很容易想到這個(gè)做法。這道題顯然可以用可持久化并查集維護(hù),用按秩合并套上一個(gè)可持久化線段樹(shù)維護(hù)fa數(shù)組。復(fù)雜度O(nlog2n),由于數(shù)據(jù)有梯度,這個(gè)做法本地測(cè)試時(shí)給了70%的分?jǐn)?shù)。但是要是又遇到跑得十分快的評(píng)測(cè)機(jī),那我也是沒(méi)辦法了。/微笑/微笑/微笑
100%做法:實(shí)際上我們并沒(méi)有基于歷史來(lái)修改fa數(shù)組,而只是基于歷史查詢(xún),所以并不需要使用真正的可持久化??紤]套用上做法一,在并查集的邊上存下這條邊建立的時(shí)間。查詢(xún)時(shí)查詢(xún)一下到并查集的根這條路徑的最小值即可知道兩個(gè)結(jié)點(diǎn)連通的時(shí)間。復(fù)雜度O(nlogn),可以拿到100%的分?jǐn)?shù)。
.
.
注意:要讀入優(yōu)化!
.
.
.
.
.
程序:
#include<iostream> #include<stdio.h> using namespace std; int f[300001],sz[300001],year[300001],n,m,x,y,t,c=0,yr=0; char zf[3]; bool bz=false;inline void read(int &x) {x=0;char c=getchar();while (c<'0' || c>'9') c=getchar();while (c>='0' && c<='9'){x=x*10+c-'0';c=getchar();} }int find(int x, int t) {while (x!=f[x]&&year[x]<=t) x=f[x];return x; }int main() {read(n);read(m);for (int i=0;i<n;i++) {f[i]=i; sz[i]=1;}while (m--) {scanf("%s",&zf);if (zf[0]=='K'){ read(c);bz=false; continue;}if (zf[0]=='R'){ read(x);read(y);if (bz==true) {if ((x+=c)>=n) x-=n;if ((y+=c)>=n) y-=n;}yr++;x=find(x,yr); y=find(y,yr);if (x==y) continue;if (sz[x]<sz[y]) {f[x]=y;sz[y]+=sz[x];year[x]=yr;} else {f[y]=x;sz[x]+=sz[y];year[y]=yr;}continue;}if (zf[0]=='T'){ read(x);read(y);read(t);if (bz=((find(x,yr-t)==find(y,yr-t))||(find(x,yr)^find(y,yr)))) printf("N\n"); else printf("Y\n");}}return 0; }轉(zhuǎn)載于:https://www.cnblogs.com/YYC-0304/p/9499924.html
總結(jié)
以上是生活随笔為你收集整理的【GDOI2016模拟3.11】历史的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【NOIP2013模拟】守卫者的挑战(期
- 下一篇: 【GDKOI2003】最大公共子串