NC200049. Mars Automaton
描述
输入描述
本题数据均匀随机生成。
输入第一行包含两个正整数n和q,之间使用一个空格符分隔,分别表示序列长度,以及操作次数。
接下来输入q行,将这样输入的第i行的第一个整数记作,表示操作类型,对应于题目描述中的三种操作,接着在这一行输入两个正整数和,含义如题目所述,相邻整数之间使用一个空格符分隔。
数据规范:
* .
* .
* .
* .* 保证除n和q外全部数据均匀随机生成(包含样例)。* 如果在随机生成数据过程中出现了的情况,则数据生成器会交换这两个值,使得其满足条件。因此输入数据保证不会出现左端点大于右端点的情况。
输出描述
对于每个3操作,输出一个整数表示操作3的查询结果,每个整数占一行。
示例1
输入:
5 7 3 2 3 2 3 4 1 2 3 1 1 3 1 4 5 1 3 5 1 4 4
输出:
1
示例2
输入:
1000 9 2 633 635 1 656 789 2 688 953 3 95 661 3 398 602 1 653 769 1 364 440 2 205 422 2 186 981
输出:
2 1
C++14(g++5.4) 解法, 执行用时: 176ms, 内存消耗: 1824K, 提交时间: 2019-12-08 22:07:50
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N = 1e5+10; int n,q,l,r,op; namespace ODT//将区间推平 { struct node{ int l,r; ll val;//[l,r]区间值为val node(){} node(int _l=-1,int _r=-1,ll _val=0):l(_l),r(_r),val(_val){} bool operator < (const node &right)const { return l<right.l; } }; typedef set<node>::iterator SIT; set<node>tr; void print() { for(SIT it=tr.begin();it!=tr.end();it++) for(int j=1;j<=(it->r)-(it->l)+1;j++) printf("%d ",it->val); } SIT split(int pos) { SIT it=tr.lower_bound(node(pos)); if(it!=tr.end()&&it->l==pos) return it; it--; node temp=*it; tr.erase(it); tr.insert(node(temp.l,pos-1,temp.val)); return tr.insert(node(pos,temp.r,temp.val)).first; } void assign(int l,int r,ll val)//第一个操作 { SIT itl=split(l),itr=split(r+1); tr.erase(itl,itr); tr.insert(node(l,r,val)); } void sum(int l,int r)//第二个操作 { SIT itl=split(l),itr=split(r+1); ll sum=0; for(SIT it=itl;it!=itr;it++) sum+=(it->val)*((it->r)-(it->l)+1); tr.erase(itl,itr); tr.insert(node(l,r-1,0)); tr.insert(node(r,r,sum)); } int query(int l,int r)//第三个询问 { set<ll>temp; SIT itl=split(l),itr=split(r+1); for(SIT it=itl;it!=itr;it++) { if(it->val!=0) temp.insert(it->val); } return temp.size(); } } using namespace ODT; int main() { scanf("%d%d",&n,&q); tr.insert(node(1,n,1)); while(q--) { scanf("%d%d%d",&op,&l,&r); if(op==1) assign(l,r,1); else if(op==2) sum(l,r); else printf("%d\n",query(l,r)); } }
C++(clang++11) 解法, 执行用时: 123ms, 内存消耗: 524K, 提交时间: 2021-03-19 12:13:17
#include <bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<int,int> PII; const int INF=0x3f3f3f3f; const int N=1e5+5; const int mod=1e9+7; struct node{ int l,r; mutable LL val; bool friend operator < (node a,node b){ return a.l<b.l; } }; set<node>s; #define IT set<node>::iterator IT split(int pos){ IT it=s.lower_bound(node{pos}); if(it!=s.end()&&it->l==pos) return it; it--; int l=it->l,r=it->r; LL val=it->val; s.erase(it); s.insert(node{l,pos-1,val}); return s.insert(node{pos,r,val}).first; } void assign(int l,int r,LL x){ IT itr=split(r+1),itl=split(l); s.erase(itl,itr); s.insert(node{l,r,x}); } void change(int l,int r){ LL sum=0; IT itr=split(r+1),itl=split(l); IT temp=itl; for(;itl!=itr;itl++) sum+=(itl->val)*(itl->r-itl->l+1); s.erase(temp,itr); if(l!=r) s.insert(node{l,r-1,0}); s.insert(node{r,r,sum}); } int query(int l,int r){ set<LL>st; IT itr=split(r+1),itl=split(l); for(;itl!=itr;itl++){ if(itl->val!=0) st.insert(itl->val); } return st.size(); } int n,q; int main(){ scanf("%d%d",&n,&q); s.insert(node{1,n,1}); while(q--){ int op,l,r; scanf("%d%d%d",&op,&l,&r); if(l>r) swap(l,r); if(op==1) assign(l,r,1); if(op==2) change(l,r); if(op==3) printf("%d\n",query(l,r)); } return 0; }