NOI模拟17
T1 卡片
似乎是个签到题,letitdown一眼切了,我看了好久才看出来这个性质
于是这个启发我们在做题的时候要观察小细节,不要站在高出思考,认真分析每一步的决策变化
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int 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<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=6e5+5;
int n,m,ans,a[N],b[N],t[N];
int lsh[N],lh;
struct XDS{
#define ls x<<1
#define rs x<<1|1
int mx[N*4];
void pushup(int x){
mx[x]=max(mx[ls],mx[rs]);
}
void ins(int x,int l,int r,int pos,int v){
if(l==r)return mx[x]=v,void();
int mid=l+r>>1;
if(pos<=mid)ins(ls,l,mid,pos,v);
else ins(rs,mid+1,r,pos,v);
pushup(x);
}
int qry(int x,int l,int r,int ql,int qr){
if(ql>qr)return 0;
if(ql<=l&&r<=qr)return mx[x];
int mid=l+r>>1,ret=0;
if(ql<=mid)ret=max(ret,qry(ls,l,mid,ql,qr));
if(qr>mid)ret=max(ret,qry(rs,mid+1,r,ql,qr));
return ret;
}
#undef ls
#undef rs
}xds;
struct ZXS{
struct POT{int ls,rs,sz;}tr[N*20];
int seg;
void pushup(int x){
tr[x].sz=tr[tr[x].ls].sz+tr[tr[x].rs].sz;
}
void ins(int &x,int y,int l,int r,int pos){
x=++seg;tr[x]=tr[y];
if(l==r)return tr[x].sz++,void();
int mid=l+r>>1;
if(pos<=mid)ins(tr[x].ls,tr[y].ls,l,mid,pos);
else ins(tr[x].rs,tr[y].rs,mid+1,r,pos);
pushup(x);
}
int qry(int x,int y,int l,int r,int ql,int qr){
if(ql>qr)return 0;
if(ql<=l&&r<=qr)return tr[y].sz-tr[x].sz;
int mid=l+r>>1,ret=0;
if(ql<=mid)ret+=qry(tr[x].ls,tr[y].ls,l,mid,ql,qr);
if(qr>mid)ret+=qry(tr[x].rs,tr[y].rs,mid+1,r,ql,qr);
return ret;
}
}zxs;int rt[N];
signed main(){
freopen("card.in","r",stdin);
freopen("card.out","w",stdout);
n=read();m=read();
fo(i,1,n){
lsh[++lh]=a[i]=read();
lsh[++lh]=b[i]=read();
}
fo(i,1,m)lsh[++lh]=t[i]=read();
sort(lsh+1,lsh+lh+1);
lh=unique(lsh+1,lsh+lh+1)-lsh-1;
fo(i,1,n){
a[i]=lower_bound(lsh+1,lsh+lh+1,a[i])-lsh;
b[i]=lower_bound(lsh+1,lsh+lh+1,b[i])-lsh;
}
fo(i,1,m)t[i]=lower_bound(lsh+1,lsh+lh+1,t[i])-lsh;
fo(i,1,m){
xds.ins(1,1,lh,t[i],i);
zxs.ins(rt[i],rt[i-1],1,lh,t[i]);
}
fo(i,1,n){
int l=a[i],r=b[i];
if(l>r)swap(l,r);
int ps=xds.qry(1,1,lh,l,r-1);
// cerr<<ps<<" "<<zxs.qry(rt[ps],rt[m],1,lh,r,lh)<<endl;
if(zxs.qry(rt[ps],rt[m],1,lh,r,lh)&1){
if(ps)ans+=lsh[l];
else ans+=lsh[b[i]];
}
else {
if(ps)ans+=lsh[r];
else ans+=lsh[a[i]];
}
// cerr<<ans<<endl;
}
printf("%lld\n",ans);
return 0;
}
T2 菜
看错题了....
数位dp,可以说是个传统套路了,我们要求前n-1个数的和大于第n个数
于是我们拆成每一位二进制考虑,转移就行了,如果你要枚举\(2^n\)的话,就T飞了
于是我们按照插头dp的样子一个一个转移就行了,状态中再加两维就好了
代码没有写,Yubai写了
T3 字符串
括号匹配,不知道是第几次做到这样的题了,这个是分治...
首先一个结论,如果是合法的那么我每次消去任意相邻的数一定可以消完
所以我们可以瞎几把合并,并且从两侧出发到某个点合并,如果可以合并那么一定是回文的!
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#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<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*t;
}
const int N=1e5+5;
const ull bas=131;
ull ba[N],cnt;
struct STA{
int sta[N],top,zhs[N],fhs[N];
STA(){top=0;zhs[0]=fhs[0]=0;}
void init(){top=0;zhs[0]=fhs[0]=0;}
void ins(int c){
if(top&&sta[top]==c)top--;
else {
sta[++top]=c;
zhs[top]=zhs[top-1]*bas+c;
fhs[top]=fhs[top-1]+ba[top-1]*c;
}
}
void ers(int c){
if(top&&sta[top]==c)top--;
else {
sta[++top]=c;
zhs[top]=zhs[top-1]*bas+c;
fhs[top]=fhs[top-1]+ba[top-1]*c;
}
}
int operator + (STA a)const{
int l=0,r=min(top,a.top),mid;
while(l<r){
mid=l+r+1>>1;
if(zhs[top]-zhs[top-mid]*ba[mid]==a.zhs[a.top]-a.zhs[a.top-mid]*ba[mid])l=mid;
else r=mid-1;
}
return zhs[top-l]*ba[a.top-l]+a.fhs[a.top-l];
}
}ls,rs,tp;
unordered_map<ull,int> mp[4];
int n,a[N],ans;char s[N];
void sol(int l,int r){
if(l==r)return ;
int mid=l+r>>1;
fu(i,r,mid+1)rs.ins(a[i]);sol(l,mid);fo(i,mid+1,r)rs.ers(a[i]);
fo(i,l,mid)ls.ins(a[i]);sol(mid+1,r);fu(i,mid,l)ls.ers(a[i]);
// cerr<<l<<" "<<r<<" "<<1.0*clock()/CLOCKS_PER_SEC<<endl;
tp.init();fo(i,1,3)mp[i].clear();
fo(i,l,mid)ls.ins(a[i]);
fu(i,mid,l){
ls.ers(a[i]);
fo(j,1,3)if(j!=a[i]){
ls.ins(j);
int l=0,r=min(ls.top,tp.top),mid;
while(l<r){
mid=l+r+1>>1;
if(ls.zhs[ls.top]-ls.zhs[ls.top-mid]*ba[mid]==tp.zhs[tp.top]-tp.zhs[tp.top-mid]*ba[mid])l=mid;
else r=mid-1;
}
ull hs=ls.zhs[ls.top-l]*ba[tp.top-l]+tp.fhs[tp.top-l];
mp[j][hs]++;ls.ers(j);
}
tp.ins(a[i]);
}
// cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
tp.init();
fu(i,r,mid+1)rs.ins(a[i]);
fo(i,mid+1,r){
rs.ers(a[i]);
fo(j,1,3)if(j!=a[i]){
rs.ins(j);
int l=0,r=min(rs.top,tp.top),mid;
while(l<r){
mid=l+r+1>>1;
if(rs.zhs[rs.top]-rs.zhs[rs.top-mid]*ba[mid]==tp.zhs[tp.top]-tp.zhs[tp.top-mid]*ba[mid])l=mid;
else r=mid-1;
}
ull hs=rs.zhs[rs.top-l]*ba[tp.top-l]+tp.fhs[tp.top-l];
ans+=mp[a[i]][hs];rs.ers(j);}
tp.ins(a[i]);
}
// cerr<<1.0*clock()/CLOCKS_PER_SEC<<endl;
// cerr<<l<<" "<<r<<endl;
}
signed main(){
freopen("string.in","r",stdin);
freopen("string.out","w",stdout);
scanf("%s",s+1);n=strlen(s+1);
ba[0]=1;fo(i,1,n)ba[i]=ba[i-1]*bas;
fo(i,1,n)a[i]=s[i]-'a'+1;
sol(1,n);printf("%lld\n",ans);
}
不要写加法啊,传参慢死哦
QQ:2953174821