codeforces 981 E. Addition on Segments(线段树+bitset)

题目链接:http://codeforces.com/contest/981/problem/E

思路:因为是查询的子集,所以其实只要看这些子集能凑出那些数字就好了,每次查询是l,r,x相当于l-r每个点加x,所以很容易可以想到用1-n之间每一个点bitset一次看有多少种数字,可如果真这么干了,肯定要T掉,所以可以配合线段树加速一下。

然后我用了bitset,#define rc (d<<1|1)这条编译就出错了,很迷,不知道为什么。。。。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%I64d",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod int(1e9+7)
#define lc (d<<1)
#define Pll pair
#define P pair
#define pi acos(-1)
int n,q;
bitset<10008> s[10008<<2];
vectorg[10008<<2];
struct as{
int l,r;}tr[10008<<2];
void build(int d,int l,int r)
{
    tr[d].l=l,tr[d].r=r,s[d][0]=1;
    if(l==r)   return;
    int mid=(l+r>>1);
    build(lc,l,mid);
    build((d<<1|1),mid+1,r);
}
void add(int d,int l,int r,int x)
{
    if(tr[d].l==l&&tr[d].r==r)
    {
        g[d].push_back(x);
        return;
    }
    int mid=(tr[d].l+tr[d].r>>1);
    if(r<=mid)      add(lc,l,r,x);
    else if(l>mid)  add((d<<1|1),l,r,x);
    else   add(lc,l,mid,x),add((d<<1|1),mid+1,r,x);
}
void query(int d,int l,int r)
{
    if(l==r)  {for(int i=0;i>1);
    if(r<=mid)    query(lc,l,r);
    else if(l>mid)   query((d<<1|1),l,r);
    else query(lc,l,mid),query((d<<1|1),mid+1,r);
    s[d]|=s[lc],s[d]|=s[(d<<1|1)];
    for(int i=0;i>n>>q;
    int x,y,z,zs=0;
    build(1,1,n);
    while(q--)
    {
        si(x),si(y),si(z);
        add(1,x,y,z);
    }
    query(1,1,n);
    FOR(i,1,n)  if(s[1][i])  zs++;
    cout<

你可能感兴趣的:(线段树)