作为水题王者前去水了一波山东理工大学的校赛,这道题一个小细节坑了我2个小时,思路其实很简单,就是线段树单点更新的模板,用一个60的数组标记,如果这个区间内有I种类的化石,那么就是1,否则为0,加入新化石的时候很容易想到,就是删除化石的时候,这个点删除了,但是如果这个区间的另外一个点有的话,那么这个区间还是要标记为1的,所以删除的时候要麻烦一点,最后,询问,用另外一个数组来保存这个区间的化石种类的有和无,需要注意的是,已经有了,赋值的时候就不需要把1的赋值取消(坑了两个小时),最后再输出就好了:
皮卡丘的梦想2
Problem Description
一天,一只住在 501 的皮卡丘决定发奋学习,成为像 LeiQ 一样的巨巨,于是他向镇上的贤者金桔请教如何才能进化成一只雷丘。
金桔告诉他需要进化石才能进化,并给了他一个地图,地图上有 n 个小镇,他需要从这些小镇中收集进化石。
接下来他会进行 q 次操作,可能是打听进化石的信息,也可能是向你询问 l 到 r 之间的进化石种类。
如果是打听信息,则皮卡丘会得到一个小镇的进化石变化信息,可能是引入了新的进化石,也可能是失去了全部的某种进化石。
如果是向你询问,你需要回答他第 l 个小镇到第 r 个小镇之间的进化石种类。
Input
首先输入一个整数 T (1 <= T <= 10),代表有 T 组数据。
每组数据的第一行输入一个整数 n (1 <= n <= 100000) 和一个整数 q (1 <= q <= 100000),分别代表有 n 个小镇,表皮卡丘有 q 次操作。
接下来输入 q 行,对于每次操作,先输入操作类型:
1: 紧接着输入 2 个整数 a(1 <= a <= n), b(1 <= b <= 60),表示第 a 个小镇引入了第 b 种进化石。
2: 紧接着输入 2 个整数 a(1 <= a <= n), b(1 <= b <= 60),表示第 a 个小镇失去了全部第 b 种进化石。
3: 紧接着输入 2 个整数 l, r (1 <= l <= r <= n),表示他想询问从第 l 个到第 r 个小镇上可收集的进化石有哪几种。
Output
对于每组输入,首先输出一行 "Case T:",表示当前是第几组数据。
每组数据中,对于每次操作 3,按编号升序输出所有可收集的进化石。如果没有进化石可收集,则输出一个小豪的百分号 "%"(不要问我为什么,出题就是这么任性)。
Example Input
1 10 10 3 1 10 1 1 50 3 1 5 1 2 20 3 1 1 3 1 2 2 1 50 2 2 20 3 1 2 3 1 10
Example Output
Case 1: % 50 50 20 50 % %
#include <iostream>
#include <stdio.h>
#include <string.h>
#define siz 100005
#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)|1)
using namespace std;
struct node{
int is[65];
int mx;
};
int p[siz];
node S[siz<<2];
int n,m;
void build(int root,int left,int right){
if(left==right){
memset(S[root].is,0,sizeof(S[root].is));
return ;
}
int mid=(left+right)>>1;
build(lson(root),left,mid);
build(rson(root),mid+1,right);
memset(S[root].is,0,sizeof(S[root].is));
}
void updata1(int root,int left,int right,int a,int b){
if(left==right){
// if(a==left)
S[root].is[b]=0;
return ;
}
int mid=(left+right)>>1;
if(a<=mid){
updata1(lson(root),left,mid,a,b);
}else{
updata1(rson(root),mid+1,right,a,b);
}
if(S[lson(root)].is[b]==1||S[rson(root)].is[b]==1){
S[root].is[b]=1;
}else{
S[root].is[b]=0;
}
}
void updata(int root,int left,int right,int a,int b){
if(a>=left&&a<=right){
// cout<<b<<endl;
S[root].is[b]=1;
}
if(left==right){
if(a==left){
S[root].is[b]=1;
}
return ;
}
int mid=(left+right)>>1;
if(a<=mid){
updata(lson(root),left,mid,a,b);
}else{
updata(rson(root),mid+1,right,a,b);
}
}
int ff[65];
void query(int root,int left,int right,int l,int r){
if(left==l&&right==r){
for(int i=1;i<=60;i++){
if(ff[i]!=1)
ff[i]=S[root].is[i];
}
return ;
}
int mid=(left+right)>>1;
// cout<<mid<<" "<<l<<" "<<r<<endl;
if(r<=mid){
query(lson(root),left,mid,l,r);
}
else if(l>=mid+1){
query(rson(root),mid+1,right,l,r);
}
else{
query(lson(root),left,mid,l,mid);
query(rson(root),mid+1,right,mid+1,r);
}
}
void solve(){
build(1,1,n);
while(m--){
memset(ff,0,sizeof(ff));
int q,a,b;
scanf("%d %d %d",&q,&a,&b);
if(q==1){
updata(1,1,n,a,b);
}
else if(q==2){
updata1(1,1,n,a,b);
}
else{
query(1,1,n,a,b);
int flag=1;
for(int i=1;i<=60;i++){
if(ff[i]!=0){
if(flag){
printf("%d",i);
flag=0;
}
else
printf(" %d",i);
}
}
if(flag){
//puts("%");
printf("%%\n");
}
else
printf("\n");
}
}
}
int main()
{
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++){
printf("Case %d:\n",i);
scanf("%d%d",&n,&m);
solve();
}
return 0;
}