題面:51nod1466
想了很久經過點撥之後纔想到做法……(NOIP要爆零啦)
其實找到關鍵突破點就知道這題怎麼做了。。。
這題的關鍵突破點就是保證起點在反對角線上
我們把行和列分開來,記錄該行(列)目前還剩下多少巧克力
每次對一行進行操作時,我們去找到列上在這一列前面的離這一列最近的剩下的巧克力少於這一列的位置(對列進行操作同理)
聽起來很拗口是不是?
就拿樣例解釋吧
比如我們要處理第2個操作,起始點是(6,1)
那麼我們就在1~5列中找到離第6列最近的小於1的位置,就是3啦(3的剩餘是0)
那麼我們就把4~6列的巧克力取走了,答案就出來了
最後呢再把這一行的信息也修改一下(和列一樣)
上述操作都可以用線段樹來解決(包括找,就是一個二分)
離散化什麼的就不再多說了(據說可以用動態開點的方法避免離散化%%%)
這題貌似使用set代碼奇短666
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <set>
#include <map>
#include <iostream>
#include <vector>
#include <queue>
#include <ctime>
#include <climits>
using namespace std;
inline int read(){
int k=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){k=k*10+ch-'0';ch=getchar();}
return k*f;
}
inline void write(int x){
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);putchar(x%10+'0');
}
inline void writeln(int x){
write(x);puts("");
}
struct ppap{int x,y,f;}a[200010];
int b[2][200010],n,m,k=0;
struct tree{
int t[800010];
inline void build(int op,int l,int r,int nod){
if(l==r){t[nod]=n-b[op^1][l]+2;return;}
int mid=(l+r)>>1;
build(op,l,mid,nod*2);build(op,mid+1,r,nod*2+1);
t[nod]=min(t[nod*2],t[nod*2+1]);
}
inline void xg(int l,int r,int x,int v,int nod){
if(l==r){t[nod]=min(t[nod],v);return;}
int mid=(l+r)>>1;
if(x<=mid)xg(l,mid,x,v,nod*2);
else xg(mid+1,r,x,v,nod*2+1);
t[nod]=min(t[nod*2],t[nod*2+1]);
}
inline void smin(int l,int r,int i,int v,int nod){
if(l>i||t[nod]>v)return;
if(l==r){k=l;return;}
int mid=(l+r)>>1;
smin(mid+1,r,i,v,nod*2+1);
if(!k)smin(l,mid,i,v,nod*2);
}//二分找位置
}t[2];
int main()
{
n=read();m=read();
for(int i=1;i<=m;i++){
a[i].x=b[0][i]=read();a[i].y=b[1][i]=read();
char c[5];scanf("%s",c);a[i].f=(c[0]=='U')?0:1;
}
sort(b[0]+1,b[0]+m+1);sort(b[1]+1,b[1]+m+1);
int M[2];
M[0]=unique(b[0]+1,b[0]+m+1)-b[0]-1;
M[1]=unique(b[1]+1,b[1]+m+1)-b[1]-1;
for(int i=1;i<=m;i++){
a[i].x=lower_bound(b[0]+1,b[0]+M[0]+1,a[i].x)-b[0];
a[i].y=lower_bound(b[1]+1,b[1]+M[1]+1,a[i].y)-b[1];
}//以上離散化
t[0].build(0,1,M[0],1);t[1].build(1,1,M[1],1);//分別維護行和列的兩棵樹
for(int i=1;i<=m;i++)if(a[i].f==1){
t[0].smin(1,M[0],a[i].x,a[i].y,1);
writeln(b[0][a[i].x]-b[0][k]);
t[1].xg(1,M[1],a[i].y,k,1);t[0].xg(1,M[0],a[i].x,a[i].y,1);//不要忘記自己這個點兩個方向都要修改
k=0;
}else{
t[1].smin(1,M[1],a[i].y,a[i].x,1);
writeln(b[1][a[i].y]-b[1][k]);
t[0].xg(1,M[0],a[i].x,k,1);t[1].xg(1,M[1],a[i].y,a[i].x,1);
k=0;
}
return 0;
}