省选模拟(20220309)
好像是之前数据结构专题没考完的题...
本来之前认为数据结构是强项,认为自己码力还是挺强的,然而现在发现根本不是码力的问题,而是想不到的问题!!
开场看T1,想到对于每个墙分治,然而没法去重啊,后来知道了可以按照括号匹配去重
T2看上去有点眼熟,后来发现要记录历史版本,然而我又不会了,答案记录的时候永久化
T3是真的不会了,现在还没有改完,似乎被卡常数了......
T1 鱼死网破
我们能想到的是,每个士兵按照墙做差分!!
查询的时候按照墙二分就行了!!
AC_code
#include<bits/stdc++.h>
using namespace std;
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=1e5+5;
struct VEC{
double x,y;double arg;int val,id;
VEC(){}VEC(double a,double b,int v,int i){x=a;y=b;arg=atan2(y,x);val=v;id=i;}
bool operator < (VEC a)const{
return arg<a.arg;
}
bool operator == (VEC a)const{
return arg==a.arg;
}
}p[105][N],sod[N],tmp[N];
int n,k,m,ans,op,a[55],b[55],c[55];
int sta[N],top,cp[105],pre[105][N];
signed main(){
freopen("clash.in","r",stdin);
freopen("clash.out","w",stdout);
n=read();k=read();m=read();op=read();
fo(i,1,n){
int x=read(),y=read();
sod[i]=VEC(x,y,0,0);
}
fo(i,1,k){a[i]=read();b[i]=read();c[i]=read();}
fo(i,1,n){int cnt=0;
fo(j,1,k){
if(c[j]>=sod[i].y)continue;
tmp[++cnt]=VEC(a[j]-sod[i].x,c[j]-sod[i].y,1,j*2-1);
tmp[++cnt]=VEC(b[j]-sod[i].x,c[j]-sod[i].y,-1,j*2);
}
sort(tmp+1,tmp+cnt+1);
// if(i==5){cerr<<"SB"<<endl;fo(j,1,cnt)cerr<<tmp[j].id<<" ";cerr<<endl;}
// cerr<<"SB"<<" "<<cnt<<endl;
fo(j,1,cnt){
if(tmp[j].val==-1){
// if(i==5)cerr<<j<<" "<<top<<" "<<tmp[j].id<<endl;
if(top==1){
// if(tmp[j].id==1)cerr<<i<<endl;
p[tmp[j].id][++cp[tmp[j].id]]=tmp[j];
// if(tmp[sta[top]].id==1)cerr<<i<<endl;
p[tmp[sta[top]].id][++cp[tmp[sta[top]].id]]=tmp[sta[top]];
}
top--;
}
else sta[++top]=j;
}
}
fo(i,1,k){
sort(p[i*2-1]+1,p[i*2-1]+cp[i*2-1]+1);
fo(j,1,cp[i*2-1])pre[i*2-1][j]=pre[i*2-1][j-1]+p[i*2-1][j].val;
sort(p[i*2]+1,p[i*2]+cp[i*2]+1);
fo(j,1,cp[i*2])pre[i*2][j]=pre[i*2][j-1]+p[i*2][j].val;
}
// cerr<<cp[1]<<endl;
while(m--){
int x=(read()^ans*op),y=(read()^ans*op);ans=0;
fo(i,1,k){VEC now=VEC(x-a[i],y-c[i],0,0);
int pos=upper_bound(p[i*2-1]+1,p[i*2-1]+cp[i*2-1]+1,now)-p[i*2-1]-1;
// cerr<<pos<<" "<<p[i*2-1][pos].val<<endl;
if(p[i*2-1][pos]==now&&p[i*2-1][pos].val==-1)pos--;
ans+=pre[i*2-1][pos];
// cerr<<i*2-1<<" "<<pos<<" "<<pre[i*2-1][pos]<<" "<<(p[i*2-1][pos+1].arg==now.arg)<<endl;
now=VEC(x-b[i],y-c[i],0,0);
pos=upper_bound(p[i*2]+1,p[i*2]+cp[i*2]+1,now)-p[i*2]-1;
if(p[i*2][pos]==now&&p[i*2][pos].val==-1)pos--;
ans+=pre[i*2][pos];
// cerr<<i*2<<" "<<pos<<" "<<pre[i*2][pos]<<endl;
}
printf("%d\n",ans=n-ans);
}
return 0;
}
T2 漏网之鱼
尤其是pushdown的时候,如果下面的都相等,那就标记永久化就行了
AC_code
#include<bits/stdc++.h>
using namespace std;
#define ull long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e6+5;
int n,a[N],mex[N];
struct XDS{
#define ls x<<1
#define rs x<<1|1
int mx[N*4],mn[N*4],tg[N*4];
ull sm[N*4],ans[N*4],hs[N*4],ts[N*4];
inline void pushup(int x,int l,int r){
mx[x]=max(mx[ls],mx[rs]);
mn[x]=min(mn[ls],mn[rs]);
sm[x]=sm[ls]+sm[rs];
ans[x]=ans[ls]+ans[rs]+hs[x]*(r-l+1);
return ;
}
inline void pushdown(int x,int l,int r){
int mid=l+r>>1;
if(ts[x]){
if(mn[ls]==mx[ls])hs[ls]+=1ull*mx[ls]*ts[x];
else ts[ls]+=ts[x];
ans[ls]+=1ull*sm[ls]*ts[x];
if(mn[rs]==mx[rs])hs[rs]+=1ull*mx[rs]*ts[x];
else ts[rs]+=ts[x];
ans[rs]+=1ull*sm[rs]*ts[x];ts[x]=0;
}
if(tg[x]){
mx[ls]=mn[ls]=tg[ls]=tg[x];
sm[ls]=1ull*tg[x]*(mid-l+1);
mx[rs]=mn[rs]=tg[rs]=tg[x];
sm[rs]=1ull*tg[x]*(r-mid);tg[x]=0;
}return ;
}
void build(int x,int l,int r){
if(l==r){
mx[x]=mn[x]=mex[l];
sm[x]=mex[l];
ans[x]=mex[l];
return ;
}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
pushup(x,l,r);return ;
}
void ins_ts(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr){
if(mn[x]==mx[x])hs[x]+=mx[x];
else ts[x]++;
ans[x]+=sm[x];
return ;
}
int mid=l+r>>1;if(tg[x]||ts[x])pushdown(x,l,r);
if(ql<=mid)ins_ts(ls,l,mid,ql,qr);
if(qr>mid)ins_ts(rs,mid+1,r,ql,qr);
pushup(x,l,r);return ;
}
ull query(int x,int l,int r,int ql,int qr){
if(ql>qr)return 0;
if(ql<=l&&r<=qr)return ans[x];
int mid=l+r>>1;ull ret=0;if(tg[x]||ts[x])pushdown(x,l,r);
if(ql<=mid)ret+=query(ls,l,mid,ql,qr);
if(qr>mid)ret+=query(rs,mid+1,r,ql,qr);
ret+=hs[x]*(min(qr,r)-max(ql,l)+1);
pushup(x,l,r);return ret;
}
void que(int x,int l,int r,int ql,int qr,int v){
if(ql>qr)return ;
if(ql<=l&&r<=qr){
if(mn[x]>v){
mx[x]=mn[x]=v;
sm[x]=1ull*v*(r-l+1);
tg[x]=v;
return ;
}
if(l==r)return ;
int mid=l+r>>1;if(tg[x]||ts[x])pushdown(x,l,r);
if(mx[rs]>v)que(rs,mid+1,r,ql,qr,v);
if(mx[ls]>v)que(ls,l,mid,ql,qr,v);
pushup(x,l,r);return ;
}
int mid=l+r>>1;if(tg[x]||ts[x])pushdown(x,l,r);
if(ql<=mid)que(ls,l,mid,ql,qr,v);
if(qr>mid)que(rs,mid+1,r,ql,qr,v);
pushup(x,l,r);return ;
}
#undef ls
#undef rs
}xds;
ull ans[N];
int Q,ll[N],rr[N],nxt[N],buc[N];
vector<int> sum[N],dc[N];
signed main(){
freopen("escape.in","r",stdin);
freopen("escape.out","w",stdout);
int sb=read();
n=read();mex[0]=1;
fo(i,1,n)a[i]=read()+1;
fo(i,1,n){
mex[i]=mex[i-1];nxt[i]=n+1;
if(a[i]<=n)nxt[buc[a[i]]]=i,buc[a[i]]=i;
else nxt[i]=0;
while(buc[mex[i]])mex[i]++;
}
xds.build(1,1,n);
Q=read();
fo(i,1,Q){
ll[i]=read();rr[i]=read();
ans[i]-=1ull*(rr[i]-ll[i]+1)*(rr[i]-ll[i]+2)/2;
dc[ll[i]-1].push_back(i);
sum[rr[i]].push_back(i);
}
fo(i,1,n){
for(int j:dc[i])ans[j]-=xds.query(1,1,n,ll[j],rr[j]);
for(int j:sum[i])ans[j]+=xds.query(1,1,n,ll[j],rr[j]);
if(i==n)continue;
xds.que(1,1,n,i+1,nxt[i]-1,a[i]);
xds.ins_ts(1,1,n,i+1,n);
// if(1.0*clock()/CLOCKS_PER_SEC>=3.99)cerr<<i<<endl;
}
fo(i,1,Q)printf("%lld\n",ans[i]);
return 0;
}
T3 浑水摸鱼
hash值,记录现在和前面第一个相同的数的距离,直接后缀排序,找lcp找不同就完事了
TLE_code
#include<bits/stdc++.h>
using namespace std;
#define ull unsigned long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
int s=0,t=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s*t;
}
const int N=5e4+5;
const ull bas=131;
ull ba[N];int n,nxt[N],pre[N];
struct ZXS{
struct POT{int ls,rs;ull sum;}tr[N*30];
int seg,rt[N];
void insert(int &x,int px,int l,int r,int pos,ull v){
if(!pos||pos>r)return ;
x=++seg;tr[x]=tr[px];
if(l==r)return tr[x].sum+=v,void();
int mid=l+r>>1;
if(pos<=mid)insert(tr[x].ls,tr[px].ls,l,mid,pos,v);
else insert(tr[x].rs,tr[px].rs,mid+1,r,pos,v);
tr[x].sum=tr[tr[x].ls].sum*ba[r-mid]+tr[tr[x].rs].sum;
return ;
}
inline void ins(int x){
if(!nxt[x]){rt[x]=rt[x-1];return ;}
insert(rt[x],rt[x-1],1,n,nxt[x],nxt[x]-x);
}
ull query(int x,int y,int l,int r,int ql,int qr){
if(ql>qr||!x)return 0;
if(ql<=l&&r<=qr)return tr[x].sum-tr[y].sum;
int mid=l+r>>1;ull ret=0;
if(ql<=mid)ret=query(tr[x].ls,tr[y].ls,l,mid,ql,qr);
if(qr>mid)ret=ret*ba[min(qr,r)-mid]+query(tr[x].rs,tr[y].rs,mid+1,r,ql,qr);
tr[x].sum=tr[tr[x].ls].sum*ba[r-mid]+tr[tr[x].rs].sum;
return ret;
}
inline ull qry(int l,int r){return query(rt[r],rt[l-1],1,n,l,r);}
}zxs;
int cnt=0;
inline bool com(int x,int y){cnt++;
int l=0,r=min(n-x+1,n-y+1),mid;
while(l<r){
mid=l+r+1>>1;
if(zxs.qry(x,x+mid-1)==zxs.qry(y,y+mid-1))l=mid;
else r=mid-1;
}
if(l==n-x+1)return true;
if(l==n-y+1)return false;
return (pre[x+l]>=x?x+l-pre[x+l]:0)<(pre[y+l]>=y?y+l-pre[y+l]:0);
}
int xl[N],buc[N],a[N];
ull ans;
signed main(){
freopen("waterflow.in","r",stdin);
freopen("waterflow.out","w",stdout);
n=read();
fo(i,1,n){
a[i]=read();
pre[i]=buc[a[i]];
nxt[buc[a[i]]]=i;
buc[a[i]]=i;
}
ba[0]=1;fo(i,1,n)ba[i]=ba[i-1]*bas;
fo(i,1,n)zxs.ins(i),xl[i]=i;
stable_sort(xl+1,xl+n+1,com);
// cerr<<cnt<<endl;
ans=n-xl[1]+1;
fo(i,2,n){
int l=0,r=min(n-xl[i-1]+1,n-xl[i]+1),mid;
while(l<r){
mid=l+r+1>>1;
if(zxs.qry(xl[i],xl[i]+mid-1)==zxs.qry(xl[i-1],xl[i-1]+mid-1))l=mid;
else r=mid-1;
}
ans+=n-xl[i]+1-l;
}
printf("%llu",ans);
}
QQ:2953174821