【Codeforces Round #365 (Div. 2)】

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值