多校联测20191009test

匿名 (未验证) 提交于 2019-12-03 00:13:02

题目:

1 文体两开花
1.1题目描述
众所周知,小G擅长文体两开花。 现在小G手中拿到了一棵树,这棵树的每个节点上都有一个非负整数权值vali。 为了展现自己深不可测的开花功底,小G会对这棵树进行一系列操作,具体表现为修改某个节点x
的权值。在每次修改之后,小G想要你告诉他,所有与节点x距离不超过2的所有节点的权值异或和是
多少。
1.2输入格式
从文件blossom.in中读入数据。 输入数据第一行包含两个正整数n,q,表示树的节点数以及修改/询问次数。
第一行n个空格隔开的正整数vali,表示每个点的权值。
接下来n~1行,每行两个正整数x,y,表示一条树边(x,y)
接下来q行,每行两个整数x,v,表示将节点x的权值修改成v
1.3输出格式
输出到文件blossom.out中。
为避免输出过量,记第i次询问的答案为ansi,你只需要输出∑(q)i=1ansi×i2109+7取模的结果即可。
1.4样例1输入
5 3
1 2 3 4 5
1 2
1 3
2 4
2 5
3 6
4 7
5 8
1.5样例1输出
117
1.6样例1解释
3次询问对应的答案分别为5,1,12
对于30%的数据,1n,q1000
对于60%的数据,1n,q105
对于100%的数据,1n,q106,1x,yn,0vali,v<230
 
sol
模拟即可:
注意直接预处理出距离为2以内的异或值,改变的时候全部改一下即可
时间复杂度O(n+q)
code:
 
 1 #include <bits/stdc++.h>  2 #pragma GCC optmize(3)  3 #define int long long  4 using namespace std;  5 int ans;  6 int n,q;  7 inline int read(){  8     int x=0,f=1;char ch=getchar();  9     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} 10     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} 11     return x*f; 12 } 13 const int N=1001000,mod=1e9+7; 14 int to[N*2],head[N],Next[N*2],dep1[N],dep2[N],a[N],fa[N]; 15 int cnt=0; 16 void add(int x,int y){to[++cnt]=y;Next[cnt]=head[x];head[x]=cnt;} 17 void dfs(int x,int ffa) 18 { 19     dep1[fa[x]]^=a[x];//预处理出与 x 同一距离根节点为1的异或值  20     dep2[fa[ffa]]^=a[x];//预处理出与 ffa 同一距离根节点为1的异或值  21     for (int i=head[x];i;i=Next[i]) 22     { 23         int u=to[i]; 24         if (u==ffa) continue; 25         fa[u]=x;//u 的父亲为 x  26         dfs(u,x); 27     } 28     //cout<<"dep1[fa[x]]= "<<dep1[fa[x]]<<" dep2[fa[ffa]]= "<<dep2[fa[ffa]]<<" fa[x]= "<<fa[x]<<" x= "<<x<<" fa[ffa]= "<<fa[ffa]<<" ffa= "<<ffa<<" a[x]= "<<a[x]<<endl; 29 } 30 signed main() 31 { 32     //freopen("blossom.in" ,"r",stdin ); 33     //freopen("blossom.out","w",stdout); 34      35     n=read();q=read(); 36     for (int i=1;i<=n;i++) a[i]=read(); 37     for (int i=1;i< n;i++) 38     { 39         int x,y; 40         x=read(); 41         y=read(); 42         add(x,y);add(y,x); 43     } 44     dfs(1,0); 45     for (int i=1;i<=q;i++) 46     { 47         int x,v; 48         x=read();v=read(); 49         //cout<<"dep1[fa[x]]= "<<dep1[fa[x]]<<" dep2[fa[fa[x]]]= "<<dep2[fa[fa[x]]]<<" fa[x]= "<<fa[x]<<" fa[fa[x]]= "<<fa[fa[x]]<<" a[x]= "<<a[x]<<" v= "<<v<<endl; 50         dep1[fa[x]]^=a[x]^v;//异或值改变  51         dep2[fa[fa[x]]]^=a[x]^v;//同理  52         a[x]=v;//更新a[x]  53          54         int anslin=dep1[x]^dep2[x]; 55         if (fa[fa[x]]) anslin^=a[fa[fa[x]]];//若有祖辈 则继续异或 ,因为祖辈不能改变之前的值  56         if (fa[x]) anslin^=a[fa[x]]^dep1[fa[x]];//若有父辈 则要加入父辈值 父辈可改变之前的值  57         else anslin^=a[x];//如果没有父辈,则肯定也没有祖辈 直接异或本身  58         ans+=1ll*anslin*i%mod*i;//边乘边模,减少复杂度  59         ans%=mod;         60 //        cout<<anslin<<endl; 61     } 62     printf("%lld\n",ans); 63     return 0; 64 } 65 /* 66 5 3 67 1 2 3 4 5 68 1 2 69 1 3 70 2 4 71 2 5 72 3 6 73 4 7 74 5 8 75  76 */

但以上代码只有60分,会T掉4个点,如果你把快读改成一个更优的话,AC100

 如下快读

 1 inline char read() {  2     static const int IN_LEN = 1000000;  3     static char buf[IN_LEN], *s, *t;  4     return (s == t ? t = (s = buf) + fread(buf, 1, IN_LEN, stdin), (s == t ? -1 : *s++) : *s++);  5 }  6 template<class T>  7 inline void read(T &x) {  8     static bool iosig;  9     static char c; 10     for (iosig = false, c = read(); !isdigit(c); c = read()) { 11         if (c == '-') iosig = true; 12         if (c == -1) return; 13     } 14     for (x = 0; isdigit(c); c = read()) x = x * 10 + (c ^ '0'); 15     if (iosig) x = -x; 16 }

 

考场上我是直接暴力枚举,使用了换根法,导致每次都跑了一遍dfs,一共q次,再加上O(n*q)的暴力枚举

导致我只拿了30分,其余全部TLE了,考场SB代码:

code:

 

  1 #include<bits/stdc++.h>   2 #pragma GCC optimize(3)   3 #define int long long   4 const int mod=1e9+7;   5 const int N=1e6+10;    6 using namespace std;   7 int yzl;   8 int n,q,w,cnt,fuck,vv;   9 int a[N];   10 int tot,ver[N],head[N],nxt[N];  11 int dep[N],depp[N],ans[N];  12 void inint(){  13     freopen("blossom.in","r",stdin);  14     freopen("blossom.out","w",stdout);  15 }  16 inline int read(){  17     int x=0,f=1;char ch=getchar();  18     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}  19     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}  20     return x*f;  21 }  22 void add(int x,int y){  23     ++tot;  24     ver[tot]=y;  25     nxt[tot]=head[x];  26     head[x]=tot;  27 }  28 void dfs(int x,int fa){  29 //    dep[x]=0;  30     depp[x]=depp[fa]+1;  31     for(int i=head[x];i;i=nxt[i]){  32         int y=ver[i];  33         if(y!=fa){  34         //    dep[y]=dep[x]+1;  35             dfs(y,x);  36             depp[y]=depp[x]+1;  37             //cout<<"dep= "<<dep[y]<<endl;  38         }  39     }  40 }  41 void dfs2(int x,int fa){  42     dep[x]=dep[fa]+1;  43     for(int i=head[x];i;i=nxt[i]){  44         int y=ver[i];  45         if(y!=fa){  46               47             dfs2(y,x);  48             w=x;  49             dep[y]=dep[x]+1;  50         //    cout<<"x= "<<x<<" y= "<<y<<endl;  51         }  52     }  53 }  54 int lowbit(int x){  55     return x&-x;  56 }  57 void change(int x,int v){  58     while(x<=n){  59         a[x]=v;  60         x+=lowbit(x);  61     }  62 }  63 signed main()  64 {  65     inint();  66     n=read(),q=read();  67     for(int i=1;i<=n;i++){  68         a[i]=read();  69     }  70     for(int i=1;i<n;i++){  71         int x,y;  72         x=read(),y=read();  73         add(x,y);  74         add(y,x);  75     }  76     dfs2(1,0);  77     cnt=0;  78     while(q--){  79         cnt++;  80         fuck=0,vv=0;  81         int x,v;  82         x=read(),v=read();  83         dfs(x,0);  84         //change(x,v);  85         a[x]=v;  86         vv=a[x];  87         for(int i=1;i<=n;i++){  88             if(abs(depp[x]-depp[i])<=2&&abs(depp[x]-depp[i])!=0){  89                   90                 ans[cnt]=vv^a[i];  91                 vv=vv^a[i];  92                 //cout<<"a[x]= "<<a[x]<<endl;  93                 //fuck=v^a[i];  94                 //cout<<"ans= "<<ans[cnt]<<" cnt= "<<cnt<<endl;  95                 //cout<<"v= "<<v<<endl;  96                 //cout<<"i= "<<i<<" a[i]= "<<a[i]<<" vv= "<<vv<<" ans[cnt]= "<<ans[cnt]<<endl;   97                 //cout<<"i= "<<i<<endl;  98             }  99         //cout<<"depp= "<<depp[i]-1<<" i= "<<i<<endl; 100     } 101      102         //cout<<dep[x]<<endl; 103     } 104     for(int i=1;i<=cnt;i++){ 105         yzl+=ans[i]*i*i; 106         //cout<<"ans[i]= "<<ans[i]<<endl; 107         //cout<<"yzl= "<<yzl<<endl; 108     } 109     printf("%lld\n",(yzl%mod)); 110     return 0; 111 } 112 /* 113 5 3  114 1 2 3 4 5  115 1 2  116 1 3  117 2 4  118 2 5  119 3 6  120 4 7  121 5 8 122  123 117 124 */

 

心得总结:尽管我现在还是弱鸡一枚连多校题只能开暴力(还是只有NOIP难度),得分现在加起来连50都没有,但是原来我可能连暴力都打不满,经过2个月的训练,代码能力也逐渐提升了。

最后还是那句话:只要坚持不懈,就一点会成功无论结果如何,只要自己尽最大的努力,也不会有遗憾了

 

 

 
 
 
 
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!