洛谷P3613 睡觉困难综合征
题目背景
刚立完Flag我就挂了WC和THUWC。。。
时间限制0.5s,空间限制128MB
因为Claris大佬帮助一周目由乃通过了Deus的题,所以一周目的由乃前往二周目世界找雪辉去了
由于二周目世界被破坏殆尽,所以由乃和雪辉天天都忙着重建世界(其实和MC差不多吧),Deus看到了题问她,总是被告知无可奉告
Deus没办法只能去三周目世界问三周目的由乃OI题。。。
三周目的世界中,因为没有未来日记,所以一切都很正常,由乃天天认真学习。。。
因为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
所以她还是只能找你帮她做了。。。
题目描述
由乃这个问题越想越迷糊,已经达到了废寝忘食的地步。结果她发现……晚上睡不着了!只能把自己的一个神经元(我们可以抽象成一个树形结构)拿出来,交给Deus。
这个神经元是一个有n个点的树,每个点的包括一个位运算opt和一个权值x,位运算有&,l,^三种,分别用1,2,3表示。
为了治疗失眠,Deus可以将一些神经递质放在点x上,初始的刺激值是。然后v依次经过从x到y的所有节点,每经过一个点i,v就变成v opti xi,所以他想问你,最后到y时,希望得到的刺激值尽可能大,所以最大值的v可以是多少呢?当然由于初始的神经递质的量有限,所以给定的初始值必须是在[0,z]之间。Deus每次都会给你3个数,x,y,z。
不过,Deus为了提升治疗效果,可能会对一些神经节点进行微调。在这种情况下,也会给三个数x,y,z,意思是把x点的操作修改为y,数值改为z
输入输出格式
输入格式:
第一行三个数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意义如题所述
输出格式:
对于每个操作1,输出到最后可以造成的最大刺激度v
输入输出样例
5 5 3 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
7 1 5
2 2 2 2 2 2 2 1 2 2 2 2 2 1 2 2 2
3
说明
对于30%的数据,n,m <= 1
对于另外20%的数据,k <= 5
对于另外20%的数据,位运算只会出现一种
对于100%的数据,0 <= n , m <= 100000 , k <= 64
树 LCT 位运算 贪心
略神的题。
基本的操作@NOI2014起床困难综合征
出到树上的话,用bitset存结点的真值表,用LCT维护一下树链,update的时候合并真值表即可。
要注意的是,LCT在reverse的时候左右子树,update的运算顺序会与实际不符。为了维护正确顺序,需要同时更新链上正向运算真值表和反向运算真值表,交换子树的时候把真值表交换。
↑否则WA一半数据(居然只有一半)
1 5 10 5 2 2 4 3 1 9 4 3 9 5 3 15 6 1 7 7 1 2 8 1 4 9 2 5 10 2 3 11 1 1 3 31 12 1 1 5 31 13 1 4 3 28 14 1 3 4 28 15 1 5 4 27 16 1 4 5 27 17 1 5 4 27 18 1 4 3 28 19 1 3 4 28
↑由于这个贪心顺序的问题,reverse的时候不能打个lazy标记就走,需要向下push一层。没注意到这个问题,多调了一个小时。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<bitset> 7 #include<vector> 8 #define LL unsigned long long 9 using namespace std; 10 const int mxn=100010; 11 LL read(){ 12 LL x=0,f=1;char ch=getchar(); 13 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 14 while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();} 15 return x*f; 16 } 17 vector<int>ve[mxn]; 18 struct node{ 19 int ch[2],fa; 20 LL val; 21 int tp;//位运算方式 22 bool rev; 23 }t[mxn]; 24 struct table{ 25 bitset<64>f[2];//真值表 //哪些位置填0/1能得到1 26 }a[mxn],b[mxn],f[mxn]; 27 inline bool isroot(int x){ 28 return t[t[x].fa].ch[0]!=x && t[t[x].fa].ch[1]!=x; 29 } 30 void init(bitset<64> &a,LL b,int tp){ 31 bitset<64> B=b; 32 if(tp==1){a=a&B;}//& 33 else if(tp==2){a=a|B;}//| 34 else if(tp==3){a=a^B;}//^ 35 return; 36 } 37 table calc(const table &x,const table &y){ 38 bitset<64>B,C; 39 B=(x.f[0]&y.f[1])|((~x.f[0])&y.f[0]); 40 C=(x.f[1]&y.f[1])|((~x.f[1])&y.f[0]); 41 return (table){B,C}; 42 } 43 void update(int rt){ 44 a[rt]=f[rt];b[rt]=f[rt]; 45 int ls=t[rt].ch[0],rs=t[rt].ch[1]; 46 if(ls){ 47 a[rt]=calc(a[ls],a[rt]);b[rt]=calc(b[rt],b[ls]); 48 } 49 if(rs){ 50 a[rt]=calc(a[rt],a[rs]);b[rt]=calc(b[rs],b[rt]); 51 } 52 return; 53 } 54 void rever(int x){ 55 t[x].rev^=1; 56 int &lc=t[x].ch[0],&rc=t[x].ch[1]; 57 swap(lc,rc); 58 swap(a[x],b[x]); 59 return; 60 } 61 void PD(int x){ 62 if(t[x].rev){ 63 rever(t[x].ch[0]); 64 rever(t[x].ch[1]); 65 t[x].rev=0; 66 } 67 return; 68 } 69 void rotate(int x){ 70 int y=t[x].fa,z=t[y].fa,lc,rc; 71 if(t[y].ch[0]==x)lc=0;else lc=1; rc=lc^1; 72 if(!isroot(y)) 73 t[z].ch[t[z].ch[1]==y]=x; 74 t[x].fa=z;t[y].fa=x; 75 t[t[x].ch[rc]].fa=y; 76 t[y].ch[lc]=t[x].ch[rc]; 77 t[x].ch[rc]=y; 78 update(y); 79 return; 80 } 81 int st[mxn],top=0; 82 void Splay(int x){ 83 st[top=1]=x; 84 for(int i=x;!isroot(i);i=t[i].fa)st[++top]=t[i].fa; 85 while(top)PD(st[top--]); 86 while(!isroot(x)){ 87 int y=t[x].fa,z=t[y].fa; 88 if(!isroot(y)){ 89 if((t[y].ch[0]==x)^(t[z].ch[0]==y))rotate(y); 90 else rotate(x); 91 } 92 rotate(x); 93 } 94 update(x); 95 return; 96 } 97 void access(int x){ 98 for(int y=0;x;x=t[x].fa){ 99 Splay(x); 100 t[x].ch[1]=y; 101 update(x); 102 y=x; 103 } 104 return; 105 } 106 int dfn[mxn]; 107 void mkroot(int x){ 108 access(x);Splay(x); 109 rever(x); 110 return; 111 } 112 void change(int x,int y,LL z){ 113 access(x); Splay(x); 114 t[x].tp=y; t[x].val=z; 115 f[x].f[1].set(); f[x].f[0].reset(); 116 init(f[x].f[0],t[x].val,t[x].tp); 117 init(f[x].f[1],t[x].val,t[x].tp); 118 update(x); 119 return; 120 } 121 void query(int x,int y,LL z){ 122 mkroot(x);access(y);Splay(y); 123 LL ans=0,now=0; 124 for(int i=63;i>=0;i--){ 125 if(a[y].f[0][i]==1){ 126 ans+=1LL<<i; 127 } 128 else if(a[y].f[1][i]==1){ 129 if(now+(1LL<<i)<=z){ 130 now+=1LL<<i; 131 ans+=1LL<<i; 132 } 133 } 134 } 135 printf("%llu\n",ans); 136 return; 137 } 138 int n,m,K; 139 void solve(){ 140 int Q,x,y;LL z; 141 for(int i=1;i<=m;i++){ 142 Q=read();x=read();y=read();scanf("%llu",&z); 143 if(Q==1) 144 query(x,y,z); 145 else 146 change(x,y,z); 147 } 148 return; 149 } 150 void Build(int x,int fa){ 151 for(int i=0;i<ve[x].size();i++){ 152 if(ve[x][i]==fa)continue; 153 t[ve[x][i]].fa=x; 154 Build(ve[x][i],x); 155 } 156 return; 157 } 158 int main(){ 159 int i,j; 160 n=read();m=read();K=read(); 161 for(i=1;i<=n;i++){ 162 t[i].tp=read(); 163 t[i].val=read(); 164 f[i].f[1].set(); 165 init(f[i].f[0],t[i].val,t[i].tp); 166 init(f[i].f[1],t[i].val,t[i].tp); 167 } 168 int u,v; 169 for(i=1;i<n;i++){ 170 u=read();v=read(); 171 ve[u].push_back(v); ve[v].push_back(u); 172 } 173 Build(1,0); 174 solve(); 175 return 0; 176 }