NOI十连测 第六测 T1

思路:

用treap动态维护,记一个sum1,sum2,注意!,写treap如果有删除操作,千万不能把权值相同的分开来。。,这在删除的时候会进入死循环,这是一个惨痛的教训。。。

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<time.h>
  7 #define ll long long
  8 struct edge{
  9     int u,v;
 10     ll w;
 11 }e[2000005];
 12 struct node{
 13     int l,r,rnd,size,w;
 14     ll v,sum1,sum2;
 15 }t[2000005];
 16 ll val[2000005];
 17 int tot,n,q,sz,vis[2000005],root;
 18 int read(){
 19     int t=0,f=1;char ch=getchar();
 20     while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1;ch=getchar();}
 21     while (‘0‘<=ch&&ch<=‘9‘) {t=t*10+ch-‘0‘;ch=getchar();}
 22     return t*f;
 23 }
 24 ll Read(){
 25     ll t=0,f=1;char ch=getchar();
 26     while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1;ch=getchar();}
 27     while (‘0‘<=ch&&ch<=‘9‘) {t=t*10+ch-‘0‘;ch=getchar();}
 28     return t*f;
 29 }
 30 void updata(int k){
 31     int l=t[k].l,r=t[k].r;
 32     t[k].size=t[l].size+t[r].size+t[k].w;
 33     int num1,num2;
 34     if (t[k].w%2==0) num1=num2=t[k].w/2;
 35     else num2=t[k].w/2,num1=num2+1;
 36     int Num=0;
 37     if (l==0&&r==0){
 38         t[k].sum1=num1*t[k].v;
 39         t[k].sum2=num2*t[k].v;
 40         return;
 41     }else
 42     if (r==0&&l!=0){
 43         t[k].sum1=t[l].sum1;
 44         t[k].sum2=t[l].sum2;
 45         if (t[l].size%2) t[k].sum2+=t[k].v*num1,t[k].sum1+=t[k].v*num2;
 46         else t[k].sum1+=t[k].v*num1,t[k].sum2+=t[k].v*num2;
 47         return;
 48     }else
 49     if (l==0&&r!=0){
 50         t[k].sum1=t[k].v*num1;
 51         t[k].sum2=t[k].v*num2;
 52         if (t[k].w%2) t[k].sum2+=t[r].sum1,t[k].sum1+=t[r].sum2;
 53         else t[k].sum1+=t[r].sum1,t[k].sum2+=t[r].sum2;
 54         return;
 55     }
 56     t[k].sum1=t[l].sum1;Num=t[l].size;
 57     t[k].sum2=t[l].sum2;
 58     if (Num%2){
 59         t[k].sum2+=t[k].v*num1;
 60         t[k].sum1+=t[k].v*num2;
 61     }else{
 62         t[k].sum2+=t[k].v*num2;
 63         t[k].sum1+=t[k].v*num1;
 64     }
 65     Num+=t[k].w;
 66     if (Num%2){
 67         t[k].sum2+=t[r].sum1;
 68         t[k].sum1+=t[r].sum2;
 69     }else{
 70         t[k].sum1+=t[r].sum1;
 71         t[k].sum2+=t[r].sum2;
 72     }
 73 }
 74 void lturn(int &k){int T=t[k].r;t[k].r=t[T].l;t[T].l=k;t[T].size=t[k].size;updata(k);updata(T);k=T;}
 75 void rturn(int &k){int T=t[k].l;t[k].l=t[T].r;t[T].r=k;t[T].size=t[k].size;updata(k);updata(T);k=T;}
 76 void insert(int &k,int v){
 77     if (!k){
 78         k=++sz;
 79         t[k].l=t[k].r=0;
 80         t[k].rnd=rand();
 81         t[k].size=1;
 82         t[k].w=1;
 83         t[k].v=v;
 84         t[k].sum1=v;
 85         t[k].sum2=0;
 86         return;
 87     }
 88     t[k].size++;
 89     if (t[k].v==v){
 90         t[k].w++;
 91         updata(k);
 92         return;
 93     }
 94     else
 95     if (t[k].v>v){
 96         insert(t[k].r,v);
 97         if (t[t[k].r].rnd<t[k].rnd) lturn(k);
 98     }else{
 99         insert(t[k].l,v);
100         if (t[t[k].l].rnd<t[k].rnd) rturn(k);
101     }
102     updata(k);
103 }
104 void del(int &k,int v){
105     if (!k) return;
106     if (t[k].v==v){
107         if (t[k].w>1){
108             t[k].w--;
109             updata(k);
110             return;
111         }
112         if (t[k].l==0||t[k].r==0){
113             k=t[k].l+t[k].r;
114             return;
115         }
116         if (t[t[k].l].rnd<t[t[k].r].rnd){
117             rturn(k);
118             del(k,v);
119         }else{
120             lturn(k);
121             del(k,v);
122         }
123         updata(k);
124         return;
125     }
126     t[k].size--;
127     if (t[k].v>v){
128         del(t[k].r,v);
129     }else{
130         del(t[k].l,v);
131     }
132     updata(k);
133 }
134 int main(){
135     n=read();q=read();int o=read();ll ans=0;
136     while (q--){
137         int opt=read();
138         if (opt==1){
139             e[++tot].u=read();e[tot].v=read();e[tot].w=Read();
140             e[tot].u^=(o*ans);e[tot].v^=(o*ans);
141             if (val[e[tot].u]) del(root,val[e[tot].u]);vis[e[tot].u]=1;
142             if (val[e[tot].v]&&e[tot].u!=e[tot].v) del(root,val[e[tot].v]);vis[e[tot].v]=1;
143             val[e[tot].u]+=e[tot].w;
144             val[e[tot].v]+=e[tot].w;
145             insert(root,val[e[tot].u]);
146             if (e[tot].u!=e[tot].v)
147             insert(root,val[e[tot].v]);
148             ans=(t[root].sum1-t[root].sum2)/2;
149             printf("%lld\n",ans);
150         }else{
151             int k=read();
152             k=k^(o*ans);
153             if (val[e[k].u])
154             del(root,val[e[k].u]);
155             if (val[e[k].v]&&e[k].u!=e[k].v)
156             del(root,val[e[k].v]);
157             val[e[k].u]-=e[k].w;
158             val[e[k].v]-=e[k].w;
159             if (val[e[k].u]!=0)
160             insert(root,val[e[k].u]);
161             if (val[e[k].v]!=0&&e[k].u!=e[k].v)
162             insert(root,val[e[k].v]);
163             ans=(t[root].sum1-t[root].sum2)/2;
164             printf("%lld\n",ans);
165         }
166     }
167     return 0;
168 }
时间: 2024-08-26 01:42:18

NOI十连测 第六测 T1的相关文章

NOI十连测 第五测 T1

1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 #include<algorithm> 6 int f[257][257],n,type,V[257],g[257][257],ans,cnt; 7 char op[204]; 8 int read(){ 9 int t=0,f=1;char ch=getchar(); 10 while

NOI十连测 第四测 T1

思路:首先每个蚂蚁移速相同,而且碰到就转头,这其实等价于擦肩而过! 看到2n个数互不相同就觉得方便多了:枚举每个数字往左或者往右作为最慢,然后考虑其他蚂蚁有多少种走路方向. (1),走的距离大于m/2 假如红色描述的是一个蚂蚁的移动轨迹,那么蓝色部分左边的蚂蚁只能向左走,蓝色右边的蚂蚁只能向右走. 而蓝色部分中的蚂蚁可以向左也可以向右,方案数为2^n,n为蓝色部分蚂蚁数量. (2),走的距离小于m/2 如图,则蓝色部分左边的蚂蚁只能向左,蓝色部分右边的蚂蚁只能向右.而蓝色部分中间不能有蚂蚁!,这

NOI十连测 DAY3 T1

这么二逼的题考试的时候我想了好久,我真是太弱了... 首先,由于ans都乘上了i*(i-1)/2,实际上要求的就是每个数的所有可能出现次数*这个数的权值. 我们发现,每个数的本质是一样的,我们记一个sum为数的总和,这样只要统计一次就OK了. 我们把每次的选择抽象成有向边,每个状态视为点,这样就构成一个有根树. 如图 我们只考虑1对答案的贡献.如图,在每层计算当前合并对答案的贡献,也就是要能得知我在这个节点选择合并1或者1的联通块,那么我能覆盖到几个叶子节点? 那么就变成O(n)的组合数学题了.

BZOJ NOI十连测 第一测 T1

思路:首先考虑t=1的情况,t等于1,那么所有位置的颜色相同,我们不用考虑概率的问题,那么,k+d*x在模d下都相等,我们考虑预处理一个数组s[i][j],代表d为i,起始位置为j的等差数列的和,这个可以证明,当模小于等于sqrt(n)的时候可以完美解决,时间复杂度为N^1.5,对于d大于sqrt(n)的情况,只需要暴力枚举就可以了. 再考虑t>=2的情况,我们选的颜色一定是颜色数最少的那个,颜色数最少的颜色的期望绝对是最小的,然后,我们分k的左边和k的右边进行计算,我们这里称呼k+d*x的位置

NOI十连测 第五测 T3

思路:考试的时候我非常地**,写了圆并,然后还TM写了半平面交和三角剖分,虽然只有30分..但是看在我写了500行的份上还是挂着吧.. 1 #include<cstdio> 2 #include<cmath> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 const double Pi=acos(-1); 7 const double eps=1e-10; 8 i

Noi 十连测 基因改造计划

SOL: 我们跑马拉车算法,然后写主席树维护. #include<bits/stdc++.h> #define LL long long #define M 6000007 #define N 260010 #define Mid (l+r>>1) using namespace std; LL allsf,allsi,allcnt; int n,m; #define sight(c) ('0'<=c&&c<='9') inline void read(

[NOI十连测] 二进制的世界

题意 给定一个长度为 n 的序列 A , 以及一种位运算 Op . 对于每个位置 x , 求 $\min_{y < x} A[y] ~ Op ~ A[x]$ . n <= 100000, 0 <= A[i] <= 65536 . 一个高效的Trick 我们可以贪心地尽可能使高的位大. g[x] 表示前 8 位为 x 的一个 vector . 我们维护 g 进行剪枝. 1 #include <cstdio> 2 #include <cstring> 3 #in

NOI十连测 第四测 T3

思路: 算法一:可以n^2找出每个点的权值,然后n^2做完,预计得分10 算法二:随机找点然后每次找最高..貌似只有10分?然而考试的时候煞笔了,边界设成inf.. 算法三:随机找几个点,然后随机爬山,听说有50~70 算法四:考虑将列分治,每次分成2部分,找出每部分边界的最大值,判断最大值左边和右边的大小,然后往大的那一边递归,预计得分70 算法五:不仅将列分治,并且将行分治,将一个n*n的矩阵划分,然后递归找,预计得分100 1 #include<bits/stdc++.h> 2 #inc

BZOJ NOI十连测 第一测 T2

思路:看到这题,就感觉是一道很熟悉的题目: http://www.cnblogs.com/qzqzgfy/p/5535821.html 只不过这题的K最多可以到N,而且边权不再只是1,考试的时候yy了一下做法: 找k次直径,第一次把边取反,要是第二次再取到同样的边,那就把它变成0,毕竟每条边只经过2次嘛,YY的很好,实际上,交上去,5分TAT 后来听以为神犇说不是取0,而是继续取反,每条边取一次就取反一次,woc.. 1 #include<cstdio> 2 #include<cmath