A
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#define LL long long
#define CLEAR(xxx) memset(xxx,0,sizeof(xxx))
using namespace std;
int main(){
int i,n;
cin>>n;
cout<<"I ";
for(i=1;i<n;i++)
if(i&1)cout<<"hate that I ";
else cout<<"love that I ";
if(n&1)cout<<"hate it";
else cout<<"love it";
return 0;
}
B
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define LL long long
const int maxn=100000+5,inf=1e9;
int n;
int main(){
LL sum=0,cnt=0,x;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%I64d",&x);
if(x!=1)sum+=x,cnt++;
if(((sum&1)^((cnt+1)&1))==1) puts("2");
else puts("1");
}
}
C. Thor
分析:用一个队列q按照时间顺序处理消息,可以处理操作1和3.。
对于操作二,维护一个值cnt,表示当前队列元素中被第二个操作查看过的消息个数。
那么ans=q.size()-cnt.
用一个链表将一个应用的消息连接起来,每次操作2后都清空这个应用的链表即可。
时间复杂度O(m) ,m是操作的次数。
代码如下:
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<cstring>
#define fst first
#define sec second
using namespace std;
const int maxn=300000+5;
inline void _read(int &x){
char ch=getchar(); bool mark=false;
for(;!isdigit(ch);ch=getchar())if(ch=='-')mark=true;
for(x=0;isdigit(ch);ch=getchar())x=x*10+ch-'0';
if(mark)x=-x;
}
int n,m,last[maxn],Next[maxn];
pair<int ,bool>q[maxn];
void Add(int x,int index){
Next[index]=last[x];
last[x]=index;
}
int main(){
int i,j,x,y;
int front=0,rear=-1,cnt=0;
_read(n); _read(m);
memset(last,-1,sizeof(last));
while(m--){
_read(x);_read(y);
if(x==1){
Add(y,++rear);
q[rear]=make_pair(y,false);
}
else if(x==2){
for(i=last[y];i!=-1;i=Next[i]){
if(i<front) break;
cnt++;
q[i].sec=true; //标记被操作2已经读过
}
last[y]=-1; //清空链表
}
else {
for(i=front;i<y;i++)
if(q[i].sec)cnt--; //维护cnt
if(front<y)front=y;
}
printf("%d\n",rear-front+1-cnt);
}
return 0;
}
分析2:线段树做法,一个数组记录新出现的消息的应用编号,线段树维护区间内被查看过的消息总数。
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=300005;
int add[maxn];
bool mark[maxn];
queue<int> q[maxn];
int tot=0,n,m;
struct node{
int a,b,sum,lazy;
};
node tree[maxn<<2];
void build_tree(int p,int x,int y){
tree[p].a=x;tree[p].b=y;tree[p].lazy=-1;
if(x<y){
int mid=(x+y)>>1;
build_tree((p<<1),x,mid);
build_tree((p<<1)+1,mid+1,y);
}
}
void putdown(int p){
int ls=(p<<1),rs=(p<<1)+1;
tree[ls].lazy=tree[p].lazy;
tree[rs].lazy=tree[p].lazy;
tree[ls].sum=tree[p].lazy*(tree[ls].b-tree[ls].a+1);
tree[rs].sum=tree[p].lazy*(tree[rs].b-tree[rs].a+1);
tree[p].sum=tree[(p<<1)].sum+tree[(p<<1)+1].sum;
tree[p].lazy=-1;
}
void change(int p,int x,int y,int d){
if(tree[p].b<x||tree[p].a>y)return;
if(tree[p].a<tree[p].b&&tree[p].lazy!=-1)putdown(p);
if(x<=tree[p].a&&tree[p].b<=y){
tree[p].lazy=d;
tree[p].sum=d*(tree[p].b-tree[p].a+1);
return;
}
change((p<<1),x,y,d);
change((p<<1)+1,x,y,d);
tree[p].sum=tree[(p<<1)].sum+tree[(p<<1)+1].sum;
}
int getsum(int p,int x,int y){
if(tree[p].a<tree[p].b&&tree[p].lazy!=-1)putdown(p);
if(tree[p].b<x||tree[p].a>y)return 0;
if(tree[p].b<=y&&tree[p].a>=x)return tree[p].sum;
else{
int total=0;
total+=getsum((p<<1),x,y);
total+=getsum(((p<<1)+1),x,y);
return total;
}
}
int main(){
int i,j,k,x,temp=0;
cin>>n>>m;
build_tree(1,1,m);
for(i=1;i<=m;i++){
scanf("%d%d",&k,&x);
if(k==1){
add[++tot]=x;
q[x].push(tot);
}
else if(k==2){
while(q[x].size()){
int t=q[x].front();
change(1,t,t,1);
q[x].pop();
}
}
else{
change(1,1,x,1);
}
printf("%d\n",tot-getsum(1,1,tot));
}
}