cf又被卡了又被卡了又被卡了……
B
题目大意
来到了一座城市,这个城市里第i个城市和第i+1座城市之间都有一条边,第n座城市和第n+1座城市之间有条边,然后有k个首都,首都和所有的城市之间都有边,任意两个城市间仅会有一条边,定义边的权值为两端节点的点权之积,求所有边的边权和。
嗯
玄学A题……
我都不知道怎么A的……
不过看我代码的意思的话……
让每一座首都只和之后的首都计算答案,然后提取公因式
嗯
难在特判0和1上……
QAQ
说不清楚了……算了
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 100000 + 5;
int n,k;
long long c[MAXN];
long long sum;
long long ans;
int mod(int x)
{
x += n;
x %= n;
return x;
}
bool sd[MAXN];
bool not_sd(int l,int r)
{
return !sd[l] && !sd[r];
}
int x;
int main()
{
scanf("%d %d",&n,&k);
for(int i = 0;i < n;i ++)
scanf("%I64d",&c[i]),sum += c[i];
long long sum_sd = 0;
for(int i = 1;i <= k;i ++)
{
scanf("%d",&x);
x --;
sd[x] = true;
sum_sd += c[x];
ans += c[x] * (sum - sum_sd);
}
for(int i = 0;i < n - !not_sd(0,n - 1);i ++)
ans += c[i] * c[mod(i + 1)] * not_sd(i,i + 1);
printf("%I64d\n",ans);
return 0;
}
D
题目大意
询问区间内出现次数为偶数的数字的异或和
……
不会做……
(Q==question A == LOI_a)
Q:畅畅畅畅~来帮我看个题
A:哦好好好
Q:就这个就这个
A:我好像做过……
……
出现次数为偶数??
这是啥……
……
好可怕
A:[l,r]的答案就是[l,r]这段区间的异或和异或一下[l,r]这段区间去重之后的异或和
Q:哎?哎哎哎?好像是哎
Q:那我是不是就可以离散化一下然后处理出到这位置都有过那些,如果有的话就算了,没有的话就异或一下标记一下?
Q:……额……好吧……
怎么办?
A:记录下下一个和它相同的数据是什么,然后用树状数组维护和,这样去查询
A:然后,将操作按照左端点排序,这样就保证当前节点是一直递增的(这个代码里会说),这样就NlogN啦~
Q:QAQ
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 1000000 + 5;
int n,L;
int tree[MAXN];
int tong[MAXN];//tong[i] = 当前最后一个i出现的位置
int nxt[MAXN];
int lsh[MAXN];
struct question
{
int l,r;
int id,ans;
}q[MAXN];
bool cmp_l(question a,question b)
{
return a.l < b.l;
}
bool cmp_id(question a,question b)
{
return a.id < b.id;
}
int where(int x)
{
return lower_bound(lsh + 1,lsh + L + 1,x) - lsh;
}
int lowbit(int x)
{
return x & -x;
}
int ask(int x)
{
int ans = 0;
while(x)
{
ans ^= tree[x];
x -= lowbit(x);
}
return ans;
}
void change(int x,int v)
{
while(x <= n)
{
tree[x] ^= v;
x += lowbit(x);
}
return;
}
int sum[MAXN];
int ask(int l,int r)
{
int ans = sum[r] ^ sum[l - 1];
return ans ^ ask(r) ^ ask(l - 1);
}
int m;
int num[MAXN];
int main()
{
scanf("%d",&n);
L = n;
for(int i = 1;i <= n;i ++)
{
scanf("%d",&num[i]);
lsh[i] = num[i];
sum[i] = sum[i - 1] ^ num[i];
nxt[i] = n + 1;
}
sort(lsh + 1,lsh + L + 1);
L = unique(lsh + 1,lsh + L + 1) - (lsh + 1);
for(int i = n;i >= 1;i --)
{
if(tong[where(num[i])])
nxt[i] = tong[where(num[i])];
tong[where(num[i])] = i;
}
for(int i = 1;i <= n;i ++)
if(tong[where(num[i])] == i)
change(i,num[i]);
scanf("%d",&m);
for(int i = 1;i <= m;i ++)
{
scanf("%d %d",&q[i].l,&q[i].r);
q[i].id = i;
}
sort(q + 1,q + m + 1,cmp_l);
int now = 1;
for(int i = 1;i <= m;i ++)
{
while(now < q[i].l)
{
change(now,num[now]);
if(nxt[now])
change(nxt[now],num[now]);
now ++;
}
q[i].ans = ask(q[i].l,q[i].r);
}
sort(q + 1,q + m + 1,cmp_id);
for(int i = 1;i <= m;i ++)
printf("%d\n",q[i].ans);
return 0;
}
//这题一个点3.5s,然后一百多个点……233333333