这套题测得时候被暴虐了。。。
T1: bzoj 4103: [Thu Summer Camp 2015]异或运算 http://www.lydsy.com/JudgeOnline/problem.php?id=4103
这题是个水题,就是以Y数列建trie,然后对于每个询问,都枚举每个X去trie上跑,就OK了,复杂度O(nplog value)
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=1011,maxm=300011;
inline int read(){
int x=0; char ch=getchar();
while (!isdigit(ch)) ch=getchar();
for (;isdigit(ch);ch=getchar()) x=x*10+ch-'0';
return x;
}
int n,m,a[maxn],b[maxm];
void init(){
n=read(); m=read();
for (int i=1;i<=n;++i) a[i]=read();
for (int i=1;i<=m;++i) b[i]=read();
}
struct Ttrie{
struct node{
node *c[2]; int sum;
}*null,e[12000000],*root[maxm];
int tot;
void clear(node &x){x.c[0]=x.c[1]=null; x.sum=0;}
node *newnode(){clear(e[++tot]); return &e[tot];}
void clear(){
tot=0; null=e; null->c[0]=null->c[1]=null; null->sum=0;
root[0]=newnode();
}
void ins(int w,int x){
node *p=root[w]=newnode(),*lp=root[w-1];
for (int i=30;i>=0;--i){
bool s=(bool)((1<sum; p->c[s]=newnode();
p=p->c[s]; lp=lp->c[s];
}
*p=*lp; ++p->sum;
}
}t;
void prepare(){
t.clear();
for (int i=1;i<=m;++i) t.ins(i,b[i]);
}
struct Tq{
int a,b,v;
Tq(){}
Tq(int a_,int b_,int v_):a(a_),b(b_),v(v_){}
};
int getans(int u,int d,int l,int r,int rank){
static Tq q[maxn<<1]; int cnt=0,res=0;
for (int i=u;i<=d;++i) q[++cnt]=Tq(i,l-1,-1);
for (int i=u;i<=d;++i) q[++cnt]=Tq(i,r,1);
static Ttrie::node *w[maxn<<1];
for (int i=1;i<=cnt;++i) w[i]=t.root[q[i].b];
for (int t=30;t>=0;--t){
int sum=0;
for (int i=1;i<=cnt;++i)
sum+=q[i].v*w[i]->c[!(bool)((1<sum;
if (sumc[(bool)((1<c[!(bool)((1<
这题非常神,深度膜拜了 http://blog.csdn.net/PoPoQQQ/article/details/46349249 之后,仍然什么都不懂,最后找PoPoQQQ问了一下,终于弄懂了 Orz
这题我们容易发现在平方时是有环的,然后发现给你的p的环长的lcm最大是60,到环的距离最大为11
于是我们维护一棵seg,每个节点有两种转态1:有点不在环上 2:所有点都在环上
第2种就在节点上维护一个链表,因为环的lcm<=60,所以链表长60就行了,update的时候把两个儿子的链表合并就是O(60nlogn)的
问题就在于第1种,如果在修改的时候碰到了第1种节点怎么打标记呢,大神给我的答案就是直接修改两个儿子,然后向上更新,这样的复杂度在一起最多是O(11nlogn)的(因为到环的距离不超过11),
于是这样复杂度就是O(60nlogn)的了
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=100011,maxmod=10011,maxc=63;
int n,m,mod,a[maxn];
void init(){
scanf("%d%d%d",&n,&m,&mod);
for (int i=1;i<=n;++i) scanf("%d",a+i);
}
int next[maxmod]; bool Incir[maxmod];
void prepare(){
static bool vis[maxmod]; memset(Incir,1,sizeof(Incir));
for (int i=0;isum=l->sum+r->sum; x->Ici=l->Ici&r->Ici;
if (x->Ici){
x->len=lcm(l->len,r->len);
int tx=l->w,ty=r->w;
for (int i=0;ilen;++i){
x->cir[i]=l->cir[tx]+r->cir[ty];
++tx; ++ty; if (tx==l->len) tx=0; if (ty==r->len) ty=0;
}
x->w=0;
}
}
void pushdown(int p){
if (!e[p].cov) return;
node *x=e+p,*l=e+(p<<1),*r=l+1;
int c=x->cov; x->cov=0; l->cov+=c; r->cov+=c;
l->w+=c; if (l->w>=l->len) l->w%=l->len; l->sum=l->cir[l->w];
r->w+=c; if (r->w>=r->len) r->w%=r->len; r->sum=r->cir[r->w];
}
void build(int p,int l,int r){
if (l==r){e[p].init(a[l]); return;}
int mid=(l+r)>>1; build(p<<1,l,mid); build(p<<1|1,mid+1,r);
update(p);
}
void clear(){build(1,1,n);}
void modify(int p,int l,int r,int fir,int las){
if (l==fir && r==las && e[p].Ici){
++e[p].cov; ++e[p].w; if (e[p].w==e[p].len) e[p].w=0;
e[p].sum=e[p].cir[e[p].w]; return;
}
if (l==r){e[p].init(next[e[p].sum]); return;}
pushdown(p); int mid=(l+r)>>1;
if (las<=mid) modify(p<<1,l,mid,fir,las);
else if (fir>mid) modify(p<<1|1,mid+1,r,fir,las);
else modify(p<<1,l,mid,fir,mid),modify(p<<1|1,mid+1,r,mid+1,las);
update(p);
}
int Query(int p,int l,int r,int fir,int las){
if (l==fir && r==las) return e[p].sum;
pushdown(p); int mid=(l+r)>>1;
if (las<=mid) return Query(p<<1,l,mid,fir,las);
if (fir>mid) return Query(p<<1|1,mid+1,r,fir,las);
return Query(p<<1,l,mid,fir,mid)+Query(p<<1|1,mid+1,r,mid+1,las);
}
void modify(int l,int r){modify(1,1,n,l,r);}
int Query(int l,int r){return Query(1,1,n,l,r);}
}seg;
void work(){
prepare(); seg.clear();
while (m--){
int op,l,r; scanf("%d%d%d",&op,&l,&r);
if (op) printf("%d\n",seg.Query(l,r));
else seg.modify(l,r);
}
}
int main(){
init();
work();
return 0;
}
这题标程非常短,但就是不明觉厉,膜拜了PPS大神后弄懂了
首先如果各不相同那就非常水了,因为最左边一列就是最右边一列排序后的。问题就在于如果有相同的不知道谁是谁了,然而可以发现在左边以x开头的对应到右边来以x结尾的相对顺序是不会变的,于是又可以找到对应关系了,这样就很水了
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=200011;
int now=0,n,a[maxn];
void init(){
scanf("%d%*d",&n); ++n;
for (int i=1;i<=n;++i){
scanf("%d",a+i);
if (!a[i]) now=i;
}
}
struct Tp{
int v,pos;
Tp(){}
Tp(int v_,int pos_):v(v_),pos(pos_){}
}q[maxn];
inline bool cmp(Tp a,Tp b){return a.v