洛谷
P9715 「QFOI R1」头
题目链接
思路:
洛谷老传统了,喜欢卡常,正常的 O ( n l o g n ) O(nlogn) O(nlogn)好像会被卡。
就是个链表题,解法看第一篇题解就行了。这里查询用的不多,更多是删除,用set来实现双向链表是比较慢的 O ( n l o g n ) O(nlogn) O(nlogn)的所以被卡掉了,只有90pts,要满分就只能写模拟双链表优化为 O ( n + m + k ) O(n+m+k) O(n+m+k)的,第19个点600+ms,慢一点都不行。
code:
#include <iostream>
#include <cstdio>
#include <set>
#include <list>
using namespace std;
const int maxn=2e6+5;
const int maxc=5e5+5;
int n,m,q,k;
long long color[maxc];
struct Data{
int op,l,r,c;
bool operator<(const Data &x)const{return true;}
};
struct Lst{
int nxt[maxn];
bool vis[maxn];
int size;
void mdy(int L,int R){
int lst=0;
for(int i=L;i<=R;i=nxt[i]){
if(vis[i])continue;
if(lst)nxt[lst]=nxt[R];
lst=i;
vis[i]=true;
size--;
}
}
int query(int L,int R){
int cnt=0;
for(int i=L;i<=R;i=nxt[i]){
if(vis[i])continue;
cnt++;
}
return cnt;
}
}L,C;
void del(Lst &L,Lst &C,int l,int r,int c){
color[c]+=1ll*L.query(l,r)*C.size;
L.mdy(l,r);
}
Data opt1[maxn],opt2[maxn];
int main(){
// cin>>n>>m>>k>>q;
scanf("%d%d%d%d",&n,&m,&k,&q);
int ct1=0,ct2=0;
for(int i=1,op,l,r,c,t;i<=q;i++){
scanf("%d%d%d%d%d",&op,&l,&r,&c,&t);
if(t==1)opt1[++ct1]=Data{op,l,r,c};
else opt2[++ct2]=Data{op,l,r,c};
}
for(int i=1;i<=n;i++)L.nxt[i]=i+1;
L.size=n;
for(int i=1;i<=m;i++)C.nxt[i]=i+1;
C.size=m;
int op,l,r,c;
for(int i=ct1;i>=1;i--){
op=opt1[i].op;
l=opt1[i].l;
r=opt1[i].r;
c=opt1[i].c;
if(op==1){
color[c]+=1ll*L.query(l,r)*C.size;
L.mdy(l,r);
}
else {
color[c]+=1ll*C.query(l,r)*L.size;
C.mdy(l,r);
}
}
for(int i=1;i<=ct2;i++){
op=opt2[i].op;
l=opt2[i].l;
r=opt2[i].r;
c=opt2[i].c;
if(op==1){
color[c]+=1ll*L.query(l,r)*C.size;
L.mdy(l,r);
}
else {
color[c]+=1ll*C.query(l,r)*L.size;
C.mdy(l,r);
}
}
for(int i=1;i<=k;i++)
printf("%lld ",color[i]);
return 0;
}