http://codeforces.com/problemset/problem/915/E
大概有几种思路:
1.动态开点线段树+标记下传
#1.1标记永久化:想了一会没想出来
1.2可以先扫一遍询问把所有需要的点建出来,然后pushdown就不管没建出来的点了,空间跟标记永久化一样
2.离散化+线段树
3.用splay维护区间(估计没人愿意去写)
4.用一个set<pair<int,int>>记所有非工作日(或工作日)区间,修改就暴力找到相关的区间去改
由于每一次操作最多多出O(1)个区间,因此尽管有时会一次删掉多个区间,但复杂度是对的
1 #include<cstdio> 2 #include<algorithm> 3 #include<set> 4 #define fi first 5 #define se second 6 using namespace std; 7 typedef pair<int,int> P; 8 set<P> s; 9 set<P>::iterator it; 10 int ans,n,q; 11 int main() 12 { 13 int i,idx,l,r;P t; 14 scanf("%d%d",&n,&q);ans=n;s.insert(P(n,1)); 15 while(q--) 16 { 17 scanf("%d%d%d",&l,&r,&idx); 18 it=s.lower_bound(P(l,0)); 19 if(it!=s.end()&&it->se<=l) 20 { 21 t=*it;s.erase(it); 22 if(l!=t.se) s.insert(P(l-1,t.se)); 23 s.insert(P(t.fi,l)); 24 } 25 it=s.lower_bound(P(r,0)); 26 if(it!=s.end()&&it->se<=r) 27 { 28 t=*it;s.erase(it); 29 if(t.fi!=r) s.insert(P(t.fi,r+1)); 30 s.insert(P(r,t.se)); 31 } 32 for(it=s.lower_bound(P(l,0));it!=s.end()&&it->fi<=r;it=s.lower_bound(P(l,0))) 33 ans-=it->fi-it->se+1,s.erase(it); 34 if(idx==2) s.insert(P(r,l)),ans+=r-l+1; 35 printf("%d ",ans); 36 } 37 return 0; 38 }