CF1479X Codeforces Round #700

C Continuous City(圖的構造)

題目大意:讓你構造一個n\le 32的有向無環無重邊圖,使得從1走到n的所有路徑長度在L,R之間,且每種長度的路徑只有唯一一條,$L,R\le 1e6$

構造圖的妙妙題目

先考慮$[1,2^{k}]$的情況

利用歸納法構圖

假設已經構造完$[1,2^{k}]$的圖,現在要構造$[1,2^{k+1}]$的圖

新點的編號爲$k+3$,把編號爲$2\sim k+2$的點,向$k+3$連一條長度爲$2^{x-2}$的邊,再把$1$和$k+3$連一條長度爲$1$的邊

這是把值域擴展的一個過程!$[1,k+2]$的每個點覆蓋的值域就是$[1,2^{k}]$

[1,1]->[2,2] [1,2]->[3,4] [1,4]->[5,8] [1,8]->[9,16] [1,16]->[17,32] 再加上1->1

如果值域大小不是$2^{k}$,利用上面的值域覆蓋的思想,我們可以再添加一個點處理$[1,S]$,最後填一個點處理$[L,R]$

 1 const int N1=35; const ll inf=0x3f3f3f3f3f3f3f3fll;
 2 
 3 int L,R;
 4 int n,m,len;
 5 int mp[N1][N1];
 6 
 7 int main()
 8 {
 9     freopen("a.in","r",stdin);
10     scanf("%d%d",&L,&R); len=R-L+1;
11     mp[1][2]=1;
12     while((1<<(n+1))<=len) n++; n+=2; 
13     for(int k=0;k<=n-3;k++)
14     {
15         mp[1][k+3]=1;
16         for(int j=2;j<=k+2;j++) mp[j][k+3]=(1<<(j-2));
17     }
18     int tmp=len;
19     if(len!=(1<<(n-2))) 
20     {
21         for(int k=n-2;k>=1;k--)
22         {
23             if(tmp>(1<<k))
24             {
25                 mp[k+2][n+1]=tmp-(1<<k);
26                 tmp-=(1<<k);
27             }
28             if(!tmp) break;
29         }
30         if(tmp==1) mp[1][n+1]=1, tmp--;
31         else if(tmp==2) mp[1][n+1]=1, mp[2][n+1]=1, tmp-=2;
32         n++;
33     }
34     if(L!=1)
35     {
36         mp[n][n+1]=L-1;
37         n++;
38     }
39     for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(mp[i][j]) m++;
40     printf("YES \n%d %d\n",n,m);
41     for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) if(mp[i][j]) 
42     {
43         printf("%d %d %d \n",i,j,mp[i][j]);
44     }
45     return 0;
46 }
View Code

 

 

D Odd Mineral Resource (隨機化異或+主席樹)

題目大意:給你一棵樹,每個點有一個權值,有$Q$個詢問,每次輸出$x,y$簡單路徑上任意一個$[L,R]$內且出現次數爲奇數次的權值$N,Q\le 3e5$

最容易想到的就是樹上莫隊了,然而$O(n\sqrt n)$會被卡掉 也可能是我常數大

  1 using namespace std;
  2 const int N1=600005; const ll inf=0x3f3f3f3f3f3f3f3fll;
  3 
  4 template<typename _T> void read(_T &ret)
  5 {
  6     ret=0; _T fh=1; char c=getchar();
  7     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
  8     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
  9     ret=ret*fh;
 10 }
 11 template<typename _T> void out(_T ret)
 12 {
 13     if(ret) out(ret/10); else return ;
 14     putchar(ret%10+'0');
 15 }
 16 struct EDGE{
 17 int to[N1],nxt[N1],head[N1],cte;
 18 void ae(int u,int v)
 19 { cte++; to[cte]=v; nxt[cte]=head[u]; head[u]=cte; }
 20 }e;
 21 
 22 int n,nn,Q,sq,S,P;
 23 int a[N1],st[N1],ed[N1],tot,pos[N1],type[N1];
 24 int ids[N1],idp[N1];
 25 
 26 struct QUES{ 
 27 int lp,rp,x,y,f,l,r,id,ans;
 28 }qu[N1];
 29 int cmp0(QUES aa,QUES bb)
 30 {
 31     if(ids[aa.lp]==ids[bb.lp]) return ids[aa.rp]<ids[bb.rp];
 32     else return ids[aa.lp]<ids[bb.lp];
 33 }
 34 int cmp1(QUES aa,QUES bb)
 35 {
 36     return aa.id<bb.id;
 37 }
 38 
 39 int ff[N1][20],dep[N1];
 40 void dfs0(int u,int fa)
 41 {
 42     st[u]=++tot; pos[tot]=u; type[tot]=1;
 43     for(int j=e.head[u];j;j=e.nxt[j])
 44     {
 45         int v=e.to[j]; if(v==fa) continue;
 46         ff[v][0]=u; dep[v]=dep[u]+1; dfs0(v,u);
 47     }
 48     ed[u]=++tot; pos[tot]=u; type[tot]=-1;
 49 }
 50 void getfa()
 51 {
 52     for(int j=1;j<=18;j++)
 53     for(int i=1;i<=n;i++)
 54         ff[i][j]=ff[ff[i][j-1]][j-1];
 55 }
 56 int lca(int x,int y)
 57 {
 58     if(dep[x]<dep[y]) swap(x,y);
 59     for(int j=18;j>=0;j--) if(dep[ff[x][j]]>=dep[y])
 60         x=ff[x][j];
 61     if(x==y) return x;
 62     int ans=0;
 63     for(int j=18;j>=0;j--) 
 64     {
 65         if(ff[x][j]!=ff[y][j]) x=ff[x][j], y=ff[y][j];
 66         else ans=ff[x][j];
 67     }
 68     return ans;
 69 }
 70 
 71 int num[N1],sum[N1],vis[N1];
 72 int L,R;
 73 void upd(int w,int p)
 74 {
 75     num[w]+=p; 
 76     if(num[w]&1) sum[idp[w]]++; else sum[idp[w]]--;
 77 }
 78 void pushx(int y)
 79 {
 80     if(vis[pos[y]]) upd(a[pos[y]],-1), vis[pos[y]]=0;
 81     else upd(a[pos[y]],1), vis[pos[y]]=1;
 82 } 
 83 int solve(int q)
 84 {
 85     int x=qu[q].x, y=qu[q].y, lw=qu[q].l ,rw=qu[q].r, F=qu[q].f;
 86     sta=clock();
 87     if(x!=F&&y!=F) pushx(st[F]);
 88     for(;R<qu[q].rp;R++) pushx(R+1);
 89     for(;qu[q].lp<L;L--) pushx(L-1);
 90     for(;qu[q].rp<R;R--) pushx(R);
 91     for(;L<qu[q].lp;L++) pushx(L);
 92     End=clock(); tt0+=End-sta; 
 93     
 94     sta=clock();
 95     if(idp[lw]==idp[rw]){
 96         for(int i=lw;i<=rw;i++) if(num[i]&1) return i;
 97     }else{
 98         for(int i=lw;i<=idp[lw]*P;i++) if(num[i]&1) return i;
 99         for(int i=(idp[rw]-1)*P+1;i<=rw;i++) if(num[i]&1) return i;
100         for(int i=idp[lw]+1;i<=idp[rw]-1;i++) if(sum[i]>=1)
101             for(int j=(i-1)*P+1;j<=i*P;j++) if(num[j]&1) return j;
102     }
103     return -1;
104 }
105 
106 int main()
107 {
108     freopen("a.txt","r",stdin);
109     freopen("a0.out","w",stdout);
110     scanf("%d%d",&n,&Q); 
111     nn=2*n; P=sqrt(n); S=1000;
112     for(int i=1;i<=n;i++) read(a[i]);
113     for(int i=1;i<=n;i++) idp[i]=(i-1)/P+1;
114     for(int i=1;i<=nn;i++) ids[i]=(i-1)/S+1;
115     int x,y,F;
116     for(int i=1;i<n;i++) read(x), read(y), e.ae(x,y), e.ae(y,x);
117     dep[1]=1; dfs0(1,0); getfa();
118     for(int q=1;q<=Q;q++) 
119     {
120         read(x), read(y), read(qu[q].l), read(qu[q].r); qu[q].id=q;
121         F=lca(x,y); qu[q].f=F;
122         if(x==F) qu[q].lp=st[x], qu[q].rp=st[y];
123         else if(y==F) qu[q].lp=st[y], qu[q].rp=st[x];
124         else{
125             if(st[x]>st[y]) swap(x,y);
126             qu[q].lp=ed[x], qu[q].rp=st[y];
127         }
128         qu[q].x=x, qu[q].y=y;
129     }
130     sort(qu+1,qu+Q+1,cmp0); 
131     L=nn+1,R=nn+1;
132     for(int q=1;q<=Q;q++) 
133     {
134         x=qu[q].x, y=qu[q].y; //l=qu[q].l, r=qu[q].r; 
135         qu[q].ans=solve(q);
136         if(x!=qu[q].f&&y!=qu[q].f) pushx(st[qu[q].f]);
137         End=clock(); tt1+=End-sta; 
138     }
139     sort(qu+1,qu+Q+1,cmp1);
140     for(int q=1;q<=Q;q++) 
141         if(qu[q].ans<0) puts("-1");
142         else out(qu[q].ans), puts("");
143     return 0;
144 }
View Code

題解提供了一種成功率很高的隨機化異或做法

考慮把點權等距拉長到$[1,2^{64}]$,維護路徑的異或和

拉長後,異或碰撞,即異或和爲$0$但存在出現奇數次的權值的概率非常低,是1/值域,$Q$次詢問也不會有多大影響

主席樹維護$f(1,x,l,r)$表示$1$到$x$路徑上所有點權在$l,r$範圍內的異或和,線段樹二分找答案

  1 using namespace std;
  2 const int N1=300005; const int M1=N1*66; const ll inf=0x3f3f3f3f3f3f3f3fll;
  3 
  4 template<typename _T> void read(_T &ret)
  5 {
  6     ret=0; _T fh=1; char c=getchar();
  7     while(c<'0'||c>'9'){ if(c=='-') fh=-1; c=getchar(); }
  8     while(c>='0'&&c<='9'){ ret=ret*10+c-'0'; c=getchar(); }
  9     ret=ret*fh;
 10 }
 11 template<typename _T> void out(_T ret)
 12 {
 13     if(ret) out(ret/10); else return ;
 14     putchar(ret%10+'0');
 15 }
 16 struct EDGE{
 17 int to[N1*2],nxt[N1*2],head[N1],cte;
 18 void ae(int u,int v)
 19 { cte++; to[cte]=v; nxt[cte]=head[u]; head[u]=cte; }
 20 }e;
 21 struct SEG{
 22 int ls[M1],rs[M1],root[N1],tot; ll xsum[M1];
 23 void upd(ll x,ll l,ll r,int r1,int &r2)
 24 {
 25     if(!r2||r1==r2){ r2=++tot; ls[r2]=ls[r1]; rs[r2]=rs[r1]; xsum[r2]=xsum[r1]^x; }
 26     if(l==r) return;
 27     ll mid=(l+r)>>1;
 28     if(x<=mid) upd(x,l,mid,ls[r1],ls[r2]);
 29     else upd(x,mid+1,r,rs[r1],rs[r2]);
 30 }
 31 inline ll calc(int r1,int r2,int r3,int r4)
 32 { return xsum[r1]^xsum[r2]^xsum[r3]^xsum[r4]; }
 33 ll query(ll L,ll R,ll l,ll r,int r1,int r2,int r3,int r4)
 34 {
 35     ll mid=(l+r)>>1;
 36     if(l==r) return calc(r1,r2,r3,r4);
 37     if(L<=l&&r<=R)
 38     {
 39         if(!calc(r1,r2,r3,r4)) return 0;
 40         if(calc(ls[r1],ls[r2],ls[r3],ls[r4])) return query(L,R,l,mid,ls[r1],ls[r2],ls[r3],ls[r4]);
 41         else return query(L,R,mid+1,r,rs[r1],rs[r2],rs[r3],rs[r4]);
 42     }
 43     ll ans=0;
 44     if(L<=mid&&!ans) ans=query(L,R,l,mid,ls[r1],ls[r2],ls[r3],ls[r4]);
 45     if(R>mid&&!ans) ans=query(L,R,mid+1,r,rs[r1],rs[r2],rs[r3],rs[r4]);
 46     return ans;
 47 }
 48 }s;
 49 
 50 int n,Q;
 51 int a[N1];
 52 map<ll,int>real; ll tra[N1];
 53 
 54 int ff[N1][20],dep[N1];
 55 void dfs0(int u,int fa)
 56 {
 57     for(int j=e.head[u];j;j=e.nxt[j])
 58     {
 59         int v=e.to[j]; if(v==fa) continue;
 60         ff[v][0]=u; dep[v]=dep[u]+1; 
 61         s.upd(tra[a[v]],1,inf,s.root[u],s.root[v]);
 62         dfs0(v,u);
 63     }
 64 }
 65 void getfa()
 66 {
 67     for(int j=1;j<=18;j++)
 68     for(int i=1;i<=n;i++)
 69         ff[i][j]=ff[ff[i][j-1]][j-1];
 70 }
 71 int lca(int x,int y)
 72 {
 73     if(dep[x]<dep[y]) swap(x,y);
 74     for(int j=18;j>=0;j--) if(dep[ff[x][j]]>=dep[y])
 75         x=ff[x][j];
 76     if(x==y) return x;
 77     int ans=0;
 78     for(int j=18;j>=0;j--) 
 79     {
 80         if(ff[x][j]!=ff[y][j]) x=ff[x][j], y=ff[y][j];
 81         else ans=ff[x][j];
 82     }
 83     return ans;
 84 }
 85 
 86 int main()
 87 {
 88     sta=clock();
 89     scanf("%d%d",&n,&Q); 
 90     for(int i=1;i<=n;i++) read(a[i]);
 91     for(int i=1;i<=n;i++) tra[i]=inf/n*i, real[inf/n*i]=i;
 92     int x,y,l,r,F; ll ans;
 93     for(int i=1;i<n;i++) read(x), read(y), e.ae(x,y), e.ae(y,x);
 94     dep[1]=1; s.upd(tra[a[1]],1,inf,0,s.root[1]);
 95     dfs0(1,0); getfa();
 96     
 97     for(int q=1;q<=Q;q++) 
 98     {
 99         read(x), read(y), read(l), read(r);
100         F=lca(x,y);
101         ans=s.query(tra[l],tra[r],1,inf,s.root[x],s.root[y],s.root[F],s.root[ff[F][0]]);
102         if(!ans) ans=-1; else ans=real[ans];
103         printf("%lld\n",ans);
104     }
105     return 0;
106 }
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章