[BZOJ]4811: [Ynoi2017]由乃的OJ
阿新 • • 發佈:2019-02-12
最大 ear tps 註冊 i++ script col P20 一個
Submit: 740 Solved: 271
[Submit][Status][Discuss]
1 7
2 6
3 7
3 6
3 1
1 2
2 3
3 4
1 5
1 1 4 7
1 1 3 5
2 1 1 3
2 3 3 3
1 1 3 2
1
5
題解: 上一題的系列套路題 但是上一題 我們用n*log^3(n)水過了 這題6s明顯是不可行的 需要優化一下復雜度 我們考慮線段樹合並 維護每一位輸入為0/1的時候輸出 然後做區間合並 這樣子平方轉移依然是3個log的 我們想想二進制優化 讓每一位對應unsigned long long每一二進制位然後把每次合並後的結果都用一個64位無符號整數存下來 這樣就成2個log了 具體怎麽合並 可以手推下
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=1e5+10; const double eps=1e-8; #define ll unsigned long long #define pii pair<ll,ll> using namespace std; struct edge{int t;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;} inline ll read() { ll ret=0; char gc=getchar(); while(gc<‘0‘||gc>‘9‘) gc=getchar(); while(gc>=‘0‘&&gc<=‘9‘) ret=ret*10+(gc-‘0‘),gc=getchar(); return ret; } ll l0[MAXN<<2],l1[MAXN<<2],r0[MAXN<<2],r1[MAXN<<2]; int opt[MAXN],n,m,k; ll a[MAXN],base; void up(int x){ l0[x]=(l1[x<<1|1]&l0[x<<1])|((~l0[x<<1])&l0[x<<1|1]); l1[x]=(l1[x<<1]&l1[x<<1|1])|((~l1[x<<1])&l0[x<<1|1]); r0[x]=(r0[x<<1|1]&r1[x<<1])|((~r0[x<<1|1])&r0[x<<1]); r1[x]=(r1[x<<1|1]&r1[x<<1])|((~r1[x<<1|1])&r0[x<<1]); } void Opt1(int x,ll y){ l0[x]=r0[x]=0; l1[x]=r1[x]=y; } void Opt2(int x,ll y){ l0[x]=r0[x]=y; l1[x]=r1[x]=base; } void Opt3(int x,ll y){ l0[x]=r0[x]=y; l1[x]=r1[x]=(base^y); } int tp[MAXN],p[MAXN],fp[MAXN],cnt; void built(int x,int l,int r){ if(l==r){ if(opt[fp[l]]==1)Opt1(x,a[fp[l]]); else if(opt[fp[l]]==2)Opt2(x,a[fp[l]]); else Opt3(x,a[fp[l]]); return ; } int mid=(l+r)>>1; built(x<<1,l,mid); built(x<<1|1,mid+1,r); up(x); } void update(int x,int l,int r,int t){ if(l==r){ if(opt[fp[l]]==1)Opt1(x,a[fp[l]]); else if(opt[fp[l]]==2)Opt2(x,a[fp[l]]); else Opt3(x,a[fp[l]]); return ; } int mid=(l+r)>>1; if(t<=mid)update(x<<1,l,mid,t); else update(x<<1|1,mid+1,r,t); up(x); } pii ans; void query1(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ ans.first=(ans.first&l1[x])|(~ans.first&l0[x]); ans.second=(ans.second&l1[x])|(~ans.second&l0[x]); return ; } int mid=(l+r)>>1; if(ql<=mid)query1(x<<1,l,mid,ql,qr); if(qr>mid)query1(x<<1|1,mid+1,r,ql,qr); } void query2(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ ans.first=(ans.first&r1[x])|(~ans.first&r0[x]); ans.second=(ans.second&r1[x])|(~ans.second&r0[x]); return ; } int mid=(l+r)>>1; if(qr>mid)query2(x<<1|1,mid+1,r,ql,qr); if(ql<=mid)query2(x<<1,l,mid,ql,qr); } int son[MAXN],num[MAXN],dep[MAXN],fa[MAXN]; void dfs1(int x,int pre,int deep){ fa[x]=pre;num[x]=1;dep[x]=deep+1; link(x)if(j->t!=pre){ dfs1(j->t,x,deep+1); num[x]+=num[j->t]; if(son[x]==-1||num[son[x]]<num[j->t])son[x]=j->t; } } void dfs2(int x,int td){ tp[x]=td;p[x]=++cnt;fp[p[x]]=x; if(son[x]!=-1)dfs2(son[x],td); link(x)if(j->t!=son[x]&&j->t!=fa[x])dfs2(j->t,j->t); } pii st[MAXN];int tot; void solve(int u,int v,ll z){ int uu=tp[u];int vv=tp[v]; ans.first=0;ans.second=base; tot=0; while(uu!=vv){ if(dep[uu]>dep[vv])query2(1,1,n,p[uu],p[u]),u=fa[uu],uu=tp[u]; else st[++tot]=mp(p[vv],p[v]),v=fa[vv],vv=tp[v]; } if(dep[u]>dep[v])query2(1,1,n,p[v],p[u]); else query1(1,1,n,p[u],p[v]); dec(i,tot,1)query1(1,1,n,st[i].first,st[i].second); ll ans1=0;ll maxx=0; for(int i=k-1;i>=0;i--){ int t1=((ans.first>>i)&1); int t2=((ans.second>>i)&1); if(t1&&t2)maxx+=(1ll<<i); else if(t1&&!t2)maxx+=(1ll<<i); else if(!t1&&t2){ if(ans1+(1ll<<i)<=z)ans1+=(1ll<<i),maxx+=(1ll<<i); } } printf("%llu\n",maxx); } int main(){ n=read();m=read();k=read(); for(int i=0;i<k;i++)base|=(1ULL<<i); inc(i,1,n)son[i]=-1; inc(i,1,n)opt[i]=read(),a[i]=read(); int u,v; inc(i,2,n)u=read(),v=read(),add(u,v),add(v,u); dfs1(1,0,0);dfs2(1,1);built(1,1,n); int x,y,op;ll z; while(m--){ op=read();x=read();y=read();z=read(); if(op==1)solve(x,y,z); else opt[x]=y,a[x]=z,update(1,1,n,p[x]); } return 0; }
4811: [Ynoi2017]由乃的OJ
Time Limit: 6 Sec Memory Limit: 256 MBSubmit: 740 Solved: 271
[Submit][Status][Discuss]
Description
由乃正在做她的OJ。現在她在處理OJ上的用戶排名問題。OJ上註冊了n個用戶,編號為1~",一開始他們按照編號 排名。由乃會按照心情對這些用戶做以下四種操作,修改用戶的排名和編號:然而由乃心情非常不好,因為Deus天 天問她題。。。因為Deus天天問由乃OI題,所以由乃去學習了一下OI,由於由乃智商挺高,所以OI學的特別熟練她 在RBOI2016中以第一名的成績進入省隊,參加了NOI2016獲得了金牌保送 Deus:這個題怎麽做呀? yuno:這個不是NOI2014的水題嗎。。。 Deus:那如果出到樹上,多組鏈詢問,帶修改呢? yuno:誒。。。??? Deus:這題叫做睡覺困難綜合征喲~ 雖然由乃OI很好,但是她基本上不會DS,線段樹都只會口胡,比如她NOI2016的分數就是100+100+100+0+100+100。 。。NOIP2017的分數是100+0+100+100+0+100所以她還是只能找你幫她做了。。。 給你一個有n個點的樹,每個點的包括一個位運算opt和一個權值x,位運算有&,l,^三種,分別用1,2,3表示。 每次詢問包含三個數x,y,z,初始選定一個數v。然後v依次經過從x到y的所有節點,每經過一個點i,v就變成v opti xi,所以他想問你,最後到y時,希望得到的值盡可能大,求最大值?給定的初始值v必須是在[0,z]之間。每次修 改包含三個數x,y,z,意思是把x點的操作修改為y,數值改為z
Input
第一行三個數n,m,k。k的意義是每個點上的數,以及詢問中的數值z都 <2^k。之後n行 每行兩個數x,y表示該點的位運算編號以及數值 之後n - 1行,每行兩個數x,y表示x和y之間有邊相連 之後m行,每行四個數,Q,x,y,z表示這次操作為Q(1位詢問,2為修改),x,y,z意義如題所述 0 <= n , m <= 100000 , k <= 64
Output
對於每個操作1,輸出到最後可以造成的最大刺激度v
Sample Input
5 5 31 7
2 6
3 7
3 6
3 1
2 3
3 4
1 5
1 1 4 7
1 1 3 5
2 1 1 3
2 3 3 3
1 1 3 2
Sample Output
71
5
HINT
Source
By 佚名提供
[BZOJ]4811: [Ynoi2017]由乃的OJ