打的big出了點小問題,maxx初值我設的0然後少了10分
第二題暴力打炸
第一題剪了一些沒用的枝依然40分
總分70
這是一次失敗的考試
string
想到和序列那個題很像,但我沒做序列,考場回憶學長講課,打不出來。最後我口胡了一個CDQ分治,大概能減很多枝比如之前5 6 修改,之後4 6修改,那麼其實你5 6不用改。
秉承這個思路,我隨意打了一個分治,然後依然40分。
題解
我們可以維護每一段區間字母個數,維護一個桶,每次詢問先把桶求出來,按照順序排序時我們可以順序枚舉26個字母,進行區間修改,然後按照逆序反過來枚舉就好了。這樣把修改操作轉化爲若干個區間修改。但單單這麼做我們會T,維護起來也不好維護,各種懶標記很噁心,我們還需要別的特殊姿勢,
if(tr[p].a) tr[p<<1].a=tr[p].a,tr[p<<1|1].a=tr[p].a;
這樣做我們修改和詢問就不用遞歸到兒子節點了,而且這樣我們還節省了維護懶標記時間
那麼我們思考如何維護
修改時
if(tr[p].l>=l&&tr[p].r<=r||tr[p].a==x){ tr[p].a=x; return ; }
若區間不完全覆蓋
if(tr[p].a) tr[p<<1].a=tr[p].a,tr[p<<1|1].a=tr[p].a,tr[p].a=0;
代碼
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1010101 struct tree{ ll x,f,a,l,r; }tr[A]; char s[A]; ll w[A]; ll n,m; map<ll,char>mp; void built(ll p,ll l,ll r){ tr[p].l=l,tr[p].r=r; if(l==r){ // printf("l=%lld s=%lld\n",l,s[l]-'a'+1ll); tr[p].a=s[l]-'a'+1; return ; } ll mid=(l+r)>>1; built(p<<1,l,mid); built(p<<1|1,mid+1,r); if(tr[p<<1].a==tr[p<<1|1].a) tr[p].a=tr[p<<1].a; } void getsum(ll p,ll l,ll r){ // printf("l=%lld r=%lld l=%lld r=%lld tr[p].a=%lld\n",tr[p].l,tr[p].r,l,r,tr[p].a); if(tr[p].l>=l&&tr[p].r<=r&&tr[p].a){ w[tr[p].a]+=(tr[p].r-tr[p].l+1); return ; } ll mid=(tr[p].l+tr[p].r)>>1; if(tr[p].a) tr[p<<1].a=tr[p].a,tr[p<<1|1].a=tr[p].a; if(mid>=l)getsum(p<<1,l,r); if(mid<r)getsum(p<<1|1,l,r); } void change(ll p,ll l,ll r,ll x){ // printf("l=%lld r=%lld ***\n",l,r); if(tr[p].l>=l&&tr[p].r<=r||tr[p].a==x){ tr[p].a=x; return ; } ll mid=(tr[p].l+tr[p].r)>>1; // printf("tr[%lld]=%lld\n",p,tr[p].a); if(tr[p].a) tr[p<<1].a=tr[p].a,tr[p<<1|1].a=tr[p].a,tr[p].a=0; if(mid>=l) change(p<<1,l,r,x); if(mid<r) change(p<<1|1,l,r,x); } void out(ll p){ // printf("p=%lld tr[p].a=%lld mp=%c\n",p,tr[p].a,mp[tr[p].a]); if(tr[p].a){ for(ll i=1;i<=tr[p].r-tr[p].l+1;i++) printf("%c",(char)mp[tr[p].a]); return ; } out(p<<1); out(p<<1|1); } void pre(){ for(ll i=1;i<=26;i++) mp[i]='a'+i-1; return ; } int main(){ pre(); scanf("%lld%lld",&n,&m); scanf("%s",s+1); built(1,1,n); for(ll i=1,a,b,c,t;i<=m;i++){ scanf("%lld%lld%lld",&a,&b,&c); getsum(1,a,b); ll l=a; if(c){ for(ll t=1;t<=26;t++) if(w[t]) change(1,l,l+w[t]-1,t),l=l+w[t],w[t]=0; } else { for(ll t=26;t>=1;t--) if(w[t]) change(1,l,l+w[t]-1,t),l=l+w[t],w[t]=0; } } out(1); puts(""); }
big
題解咕咕咕
代碼
#include<bits/stdc++.h> #define ll long long #define A 6000000 using namespace std; ll tire[A][2],t[A],sum[A],dl[A],a[A]; ll tot=1,n,m,maxx=0,ans=0; bool pan; ll change(ll x){ return (2*x/(1<<n)+2*x)%(1<<n); } bool cmp(ll x,ll y){ return x>y; } inline void insert(ll x) { ll p=1; for(ll i=1;i<=n;i++) { ll zan=(x>>(n-i))&1; // printf("zan=%lld tot=%lld\n",zan,tot); if(!tire[p][zan]) tire[p][zan]=++tot; p=tire[p][zan]; } } inline ll dfs(ll x,ll zhi,ll deep) { if(deep<0){ dl[++dl[0]]=zhi; } // printf("trie[0][1]=[%lld][%lld] deep=%lld zhi=%lld 1<<=%lld\n",tire[x][0],tire[x][1],deep,zhi,1ll<<deep); if(tire[x][0]&&!tire[x][1]) dfs(tire[x][0],zhi^(1ll<<deep),deep-1); if(!tire[x][0]&&tire[x][1]) dfs(tire[x][1],zhi^(1ll<<deep),deep-1); if(tire[x][0]&&tire[x][1]){ dfs(tire[x][0],zhi,deep-1);dfs(tire[x][1],zhi,deep-1); } } int main() { scanf("%lld%lld",&n,&m); for(ll i=1;i<=m;i++) scanf("%lld",&a[i]); for(ll i=m;i>=1;i--) sum[i]=sum[i+1]^a[i]; for(ll i=0,now=0;i<=m;i++){ // printf("now=%lld add=%lld\n",now,now^sum[i+1]); now=now^change(a[i]); insert(now^sum[i+1]); } // printf("1 %lld 0%lld\n",tire[1][1],tire[1][0]); dfs(1,0,n-1); sort(dl+1,dl+dl[0]+1,cmp); for(ll i=1;i<=dl[0];i++) if(dl[i]==dl[1]) ans++; printf("%lld\n%lld\n",dl[1],ans); }