题目
题解思路
看的出是线段树,一开始想用线段树的操作来模拟操作一,但是好像弄不出。
这里就有个性质了,当你要修改某段为1的时候你查询它的总和不为它的长度时,只需将总和改成长度然后pd一下就行了。
但是这个从哪里开始哪里结束要怎么返回呢?
利用前缀和的单调性就能得到这段有几个被填上了的。
所以我们可以进行二分,二分出那个没被填上的第一个点,以及二分出填的时候结束的位置(这里利用上面的性质,我们只需知道两个端点将他们的sum改成长度然后pd即可)
这里的二分属实巧妙啊
int ans1 = n + 1 , ans2 = n+1 ;
int l = t2 , r = n ;
while ( l <= r )
{
int mid = l+r >> 1 ;
int sum = sea(1,l,mid) ;
if ( sum == mid - l + 1 )
l = mid + 1 ;
else
r = mid - 1 , ans1 = mid ;
}
l = ans1 , r = n ;
while ( l <= r )
{
int mid = l + r >> 1 ;
int sum = mid - ans1 + 1 - sea(1,ans1,mid);
if (sum >= t3 )
r = mid - 1 , ans2 = mid ;
else
l = mid + 1 ;
}
if (ans1 > n || ans2 > n )
cout << "0\n";
else
cout << ans1 << " " << ans2 << "\n" ;
_add(1,min(n,ans1),min(n,ans2),1) ;
这里对线段树的操作倒是没有多少,pd为2sum改成0,pd为1改成长度。
线段树的题写太少了。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
struct node
{
int sum;
int l,r,lz;
};
const int N = 1001000 ;
node tee[4*N];
int n , cnt = 0 , m ;
void in(int i , int t1 , int t2)
{
tee[i].l = t1 , tee[i].r = t2;
if ( t1 == t2 )
{
tee[i].sum = 0;
tee[i].lz = 0 ;
return ;
}
int j = (t1+t2)/2;
in(i*2,t1,j);
in(i*2+1,j+1,t2);
tee[i].sum = tee[i*2].sum+tee[i*2+1].sum;
tee[i].lz = 0 ;
}
void pd(int i )
{
if ( tee[i].lz != 0 )
{
tee[i*2].lz = tee[i].lz;
tee[i*2+1].lz = tee[i].lz;
tee[i*2].sum = tee[i*2].lz == 1 ? tee[i*2].r - tee[i*2].l + 1 : 0 ;
tee[i*2+1].sum = tee[i*2+1].lz == 1 ? tee[i*2+1].r - tee[i*2+1].l + 1 : 0 ;
tee[i].lz = 0 ;
}
}
long long sea( int i ,int t1 , int t2 )
{
if ( tee[i].l >= t1 && tee[i].r <= t2 )
return tee[i].sum;
pd(i);
long long sum = 0 ;
if ( tee[i*2].r >= t1 )
sum += sea(i*2,t1,t2);
if ( tee[i*2+1].l <= t2 )
sum += sea(i*2+1,t1,t2);
return sum;
}
void _add( int i , int t1 , int t2 ,int vv )
{
int l = tee[i].l , r = tee[i].r ;
if ( l >= t1 && r <= t2 )
{
tee[i].lz = vv ;
tee[i].sum = tee[i].lz == 1 ? r - l + 1 : 0 ;
return ;
}
pd(i);
if ( tee[i*2].r >= t1)
_add(i*2,t1,t2,vv);
if (tee[i*2+1].l <= t2)
_add(i*2+1,t1,t2,vv);
tee[i].sum = tee[i*2].sum + tee[i*2+1].sum;
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> n >> m ;
in(1,1,n) ;
for (int i = 1 ; i <= m ; i++ )
{
int t1 ,t2 , t3 ;
cin >> t1 >> t2 >> t3 ;
if ( t1 == 1 )
{
int ans1 = n + 1 , ans2 = n+1 ;
int l = t2 , r = n ;
while ( l <= r )
{
int mid = l+r >> 1 ;
int sum = sea(1,l,mid) ;
if ( sum == mid - l + 1 )
l = mid + 1 ;
else
r = mid - 1 , ans1 = mid ;
}
l = ans1 , r = n ;
while ( l <= r )
{
int mid = l + r >> 1 ;
int sum = mid - ans1 + 1 - sea(1,ans1,mid);
if (sum >= t3 )
r = mid - 1 , ans2 = mid ;
else
l = mid + 1 ;
}
if (ans1 > n || ans2 > n )
cout << "0\n";
else
cout << ans1 << " " << ans2 << "\n" ;
_add(1,min(n,ans1),min(n,ans2),1) ;
}else
{
cout << sea(1,t2,t3) << "\n" ;
_add(1,t2,t3,2) ;
}
}
return 0 ;
}