codeforces 365

来源:互联网 发布:sql当前时间减去1小时 编辑:程序博客网 时间:2024/04/30 06:54

A:略

B:给出n个点,所有的点要以1>2>3.....n>1,的连接道路成为一个环,这n个点当中有k个capital,这k个capital必须和所有的点有直接通道,

每一个点有一个权值,每一条道路的权值为两端点u,v的权值之积。

问总的权值之和


先把每个点围成的环形的道路的值算出来,再枚举每一个capita,计算这个点和除了相邻点连接的路的权值之和,其实就是总权值减去当前点相邻点和已经计算的capital点(因为两点之间只能有一条路,set判断)的权值,乘以该点的权值即可

要特判已经计算的点是否是相邻点!

#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>#include<set>using namespace std;typedef long long ll;int n,k;ll c[100050],tot;set<int> s;int main(){scanf("%d%d",&n,&k);ll ans=0;for (int i=1;i<=n;i++) scanf("%lld",&c[i]),tot+=c[i];c[n+1]=c[1];c[0]=c[n];for (int i=1;i<=n;i++) ans+=c[i]*c[i+1];int x;for (int i=1;i<=k;i++){scanf("%d",&x);ll h=tot-c[x];if (s.find(x==1?n:x-1)==s.end()) h-=c[x-1];if (s.find(x==n?1:x+1)==s.end()) h-=c[x+1];ans+=c[x]*h;tot-=c[x];s.insert(x);}printf("%lld",ans);return 0;}


D:给定序列,求l~r的区间内所有出现了偶数次的数的异或和


如果是求出现了单数次的就好办了,就是求这个区间的异或值即可(预处理前缀异或值,差分取区间异或即可)

//刚开始想用线段树。。实际上像这种满足结合律交换律乱七八糟律的,乘法加法异或,如果只有询问,直接前缀和差分取区间即可

既然是偶数次,也不难想到就是再异或一下该区间所有不重复的数的异或值而已。实际上,将询问按r排序,维护一个值最后出现的位置,用线段树来维护一个区间内出现

的不重复的数,因为已经排好序,从左向右扫,也记录了一个值出现的最后位置,那么每询问一个区间的不重复异或值,就是在线段树中提取这个区间即可。

为什么这样做?这样可以保证数据结构中每个数只出现一次,这样取异或值的时候就能保证是不重复异或,并且要让排序后,以r结尾的区间尽量多的包含这个数,那么就要记录最后出现的位置,算是一种方法把

题意:给你n个数,m个区间询问 求区间出现次数为偶数次的数的异或和 

那么如何快速计算一个区间内不同的数的异或和呢?离线处理,结构体存储每个查询区间的左右边界,按照右边界排序,从左向右遍历序列 树状数组维护 不断的将数添加到树状数组,若当前位置的数存在前驱,则删除前驱 (删除就是再进行一次异或a^a=0) 对于共右边界的查询区间 一次遍历得到答案,然后继续遍历。



关于实现,先挖个坑。。。


其实这个题求区间不重复异或值,只要求单点更新异或值(因为异或,删除就是再插入一次),和询问一个区间的异或值,不必要线段树,树状数组即可

#include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>#include<map>using namespace std;typedef int ll;inline int read(){int ans,f=1;char ch;while ((ch=getchar())<'0'||ch>'9') if (ch=='-') f=-1;ans=ch-'0';while ((ch=getchar())>='0'&&ch<='9') ans=ans*10+ch-'0';return ans*f;}inline int lowbit(int x){return x&(-x);}struct aa{int l,r,id;bool operator <(const aa &b) const{return r<b.r;}}que[1000050];map<int,int> last;int n,m;ll a[1000050],qz[1000050],ans[1000050];ll tr[1000050];void insert(int x){int i=x;while (i<=n){tr[i]^=a[x];i+=lowbit(i);}}ll query(int i){int ans=0;while (i>0){ans^=tr[i];i-=lowbit(i);}return ans;}int main(){n=read();for (int i=1;i<=n;i++) a[i]=read(),qz[i]=qz[i-1]^a[i];m=read();for (int i=1;i<=m;i++) que[i].l=read(),que[i].r=read(),que[i].id=i;sort(que+1,que+m+1);int now=0;for(int i=1;i<=m;i++){while (now<que[i].r){now++;int k=last[a[now]];if (k) insert(k);last[a[now]]=now;insert(now);}ans[que[i].id]=query(que[i].r)^query(que[i].l-1)^(qz[que[i].r]^qz[que[i].l-1]);}for (int i=1;i<=m;i++) printf("%d\n",ans[i]);return 0; } 



0 0