这一轮是要闹哪样啊???前十都死活进不去???
能不能不要到联赛前突然连续掉链子啊!!!
总算难得的切掉了T1。然后又一次把T2和T3的难度估反了
结果给T2剩下了30分钟,想到正解来不及打了。
然后T3没有乱搞丢了很多分。(循环不用跑满,上限能到80。。。考后还有AC的)
联赛题目的难度基本是升序。。。
学会乱搞,要有信仰。。。
T1必须占用更少的时间,想到并证明正确之后就快速打出来
T1:Dave打扑克
可以证明,数量本质不同的堆数至多为根号个。
所以并查集维护,用unordered_set迭代器遍历,用树状数组计数询问即可。
1 #include<cstdio> 2 #include<unordered_set> 3 using namespace std; 4 unordered_set<int>S; 5 int n,m,t[200005],buc[200005],siz[100005],f[100005]; 6 void add(int p,int w){for(;p<=200000;p+=p&-p)t[p]+=w;} 7 int ask(int p,int a=0){for(;p;p^=p&-p)a+=t[p];return a;} 8 int find(int p){return f[p]==p?p:f[p]=find(f[p]);} 9 int main(){//freopen("cards105.in","r",stdin);freopen("my.out","w",stdout); 10 scanf("%d%d",&n,&m); 11 buc[1]=n;S.insert(1);add(1,n); 12 for(int i=1;i<=n;++i)f[i]=i,siz[i]=1; 13 for(int i=1,opt,x,y;i<=m;++i){ 14 scanf("%d",&opt); 15 if(opt==1){ 16 scanf("%d%d",&x,&y); 17 x=find(x);y=find(y); 18 if(x==y)continue; 19 add(siz[x],-1);add(siz[y],-1);add(siz[x]+siz[y],1); 20 buc[siz[x]]--;buc[siz[y]]--;buc[siz[x]+siz[y]]++; 21 if(!buc[siz[x]])S.erase(siz[x]); 22 if(!buc[siz[y]])S.erase(siz[y]); 23 if(buc[siz[x]+siz[y]]==1)S.insert(siz[x]+siz[y]); 24 siz[y]+=siz[x];f[x]=y;n--; 25 }else{ 26 scanf("%d",&x);long long ans=n*(n-1ll)>>1; 27 if(!x){printf("%lld\n",ans);continue;} 28 unordered_set<int>::iterator it=S.begin(); 29 while(it!=S.end()){ 30 y=*it; 31 ans-=1ll*buc[y]*(ask(y+x-1)-ask(y)); 32 ans-=1ll*buc[y]*(buc[y]-1)>>1; 33 it++; 34 }printf("%lld\n",ans); 35 } 36 } 37 }