YbtOJ-变量观测【鸽笼原理】
生活随笔
收集整理的這篇文章主要介紹了
YbtOJ-变量观测【鸽笼原理】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目大意
有nnn個數字開始都是000,要求有qqq次操作。
強制在線
1≤n,q≤2×105,1≤k≤3,1≤t,v≤1061\leq n,q\leq 2\times 10^5,1\leq k\leq 3,1\leq t,v\leq 10^61≤n,q≤2×105,1≤k≤3,1≤t,v≤106
解題思路
考慮從kkk入手,根據鴿籠原理,一個觀測員觀測結束當且僅當存在它觀測的一個數字a≥?tk?a\geq \lceil\frac{t}{k}\rceila≥?kt??,注意到此時已經至少填充了?tk?\lceil\frac{t}{k}\rceil?kt??。
所以我們可以對于每個它觀測的數字以?tk?\lceil\frac{t}{k}\rceil?kt??為界,當到倒打這個界時,我們直接重新根據現在的數字再來一次,也就是把ttt剩余的部分再分成kkk份丟回去。
一直這樣做知道合法為止,此時每次會至少令t=k?1ktt=\frac{k-1}{k}tt=kk?1?t,所以這樣的次數應該為log?kk?1t\log_{\frac{k}{k-1}}tlogk?1k??t。
用個setsetset維護就好了,時間復雜度:O(qlog?kk?1tklog?q)O(q\log_{\frac{k}{k-1}}tk\log q)O(qlogk?1k??tklogq)
code
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<set> #include<cmath> #define ll long long #define mp(x,y) make_pair(x,y) using namespace std; const ll N=2e5+10; ll n,m,cnt,a[N],t[N]; vector<ll> ans,q[N],c[N]; set<pair<ll,ll> >s[N]; void update(ll x){ll sum=0;for(ll i=0;i<q[x].size();i++){ll y=q[x][i];sum+=a[y];s[y].erase(mp(c[x][i],x));}if(sum>=t[x])ans.push_back(x);else{for(ll i=0;i<q[x].size();i++){ll y=q[x][i];c[x][i]=a[y]+ceil((double)(t[x]-sum)/q[x].size());s[y].insert(mp(c[x][i],x));}}return; } signed main() { // freopen("obs.in","r",stdin); // freopen("obs.out","w",stdout);scanf("%lld%lld",&n,&m);ll las=0;while(m--){ll op;scanf("%lld",&op);if(op==1){ll k,sum=0;++cnt;scanf("%lld%lld",&t[cnt],&k);t[cnt]^=las;for(ll i=0,x;i<k;i++){scanf("%lld",&x);x^=las;q[cnt].push_back(x);sum+=a[x];c[cnt].push_back(a[x]+ceil((double)t[cnt]/k));s[x].insert(mp(c[cnt][i],cnt));}t[cnt]+=sum;}else{ans.clear();ll p,w;scanf("%lld%lld",&p,&w);p^=las;w^=las;a[p]+=w;while(!s[p].empty()){pair<ll,ll> k=*s[p].begin();if(a[p]>=k.first)update(k.second);else break;}printf("%lld",las=ans.size());sort(ans.begin(),ans.end());for(ll i=0;i<ans.size();i++)printf(" %lld",ans[i]);putchar('\n');}}return 0; }總結
以上是生活随笔為你收集整理的YbtOJ-变量观测【鸽笼原理】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 3D效果图电脑配置(3d效果图电脑配置)
- 下一篇: 仙剑五电脑配置(仙5电脑配置)